From 0ee5882bc3dc366e3b44ab0c766bd747d65d35c6 Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 27 May 2026 14:41:48 +0200 Subject: [PATCH 01/57] Added ACCESS_LOCAL_NETWORK permission for android 17 --- permission_handler_android/CHANGELOG.md | 3 + .../PermissionConstants.java | 105 ++- .../permissionhandler/PermissionUtils.java | 659 +++++++++++++----- permission_handler_android/pubspec.yaml | 2 +- permission_handler_apple/CHANGELOG.md | 4 + .../ios/Classes/PermissionHandlerEnums.h | 3 +- permission_handler_apple/pubspec.yaml | 2 +- permission_handler_html/CHANGELOG.md | 4 + permission_handler_html/pubspec.yaml | 2 +- .../CHANGELOG.md | 4 + .../lib/src/permissions.dart | 5 + .../pubspec.yaml | 2 +- permission_handler_windows/CHANGELOG.md | 4 + permission_handler_windows/pubspec.yaml | 2 +- .../windows/permission_constants.h | 3 +- 15 files changed, 582 insertions(+), 222 deletions(-) diff --git a/permission_handler_android/CHANGELOG.md b/permission_handler_android/CHANGELOG.md index dfec82c83..dd342199a 100644 --- a/permission_handler_android/CHANGELOG.md +++ b/permission_handler_android/CHANGELOG.md @@ -1,3 +1,6 @@ +## 13.0.2 + +* Added support for the new Android 17 permission `ACCESS_LOCAL_NETWORK` ## 13.0.1 diff --git a/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionConstants.java b/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionConstants.java index 0262db176..734aa019f 100644 --- a/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionConstants.java +++ b/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionConstants.java @@ -1,13 +1,13 @@ package com.baseflow.permissionhandler; import androidx.annotation.IntDef; - import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; final class PermissionConstants { + static final String LOG_TAG = "permissions_handler"; static final int PERMISSION_CODE = 24; static final int PERMISSION_CODE_IGNORE_BATTERY_OPTIMIZATIONS = 209; @@ -17,7 +17,6 @@ final class PermissionConstants { static final int PERMISSION_CODE_ACCESS_NOTIFICATION_POLICY = 213; static final int PERMISSION_CODE_SCHEDULE_EXACT_ALARM = 214; - // PERMISSION_GROUP // Deprecated in favor of PERMISSION_GROUP_CALENDAR_WRITE_ONLY and @@ -62,48 +61,50 @@ final class PermissionConstants { static final int PERMISSION_GROUP_CALENDAR_FULL_ACCESS = 37; static final int PERMISSION_GROUP_ASSISTANT = 38; static final int PERMISSION_GROUP_BACKGROUND_REFRESH = 39; + static final int PERMISSION_GROUP_ACCESS_LOCAL_NETWORK = 40; @Retention(RetentionPolicy.SOURCE) @IntDef({ - PERMISSION_GROUP_CALENDAR, - PERMISSION_GROUP_CAMERA, - PERMISSION_GROUP_CONTACTS, - PERMISSION_GROUP_LOCATION, - PERMISSION_GROUP_LOCATION_ALWAYS, - PERMISSION_GROUP_LOCATION_WHEN_IN_USE, - PERMISSION_GROUP_MEDIA_LIBRARY, - PERMISSION_GROUP_MICROPHONE, - PERMISSION_GROUP_PHONE, - PERMISSION_GROUP_PHOTOS, - PERMISSION_GROUP_REMINDERS, - PERMISSION_GROUP_SENSORS, - PERMISSION_GROUP_SENSORS_ALWAYS, - PERMISSION_GROUP_SMS, - PERMISSION_GROUP_SPEECH, - PERMISSION_GROUP_STORAGE, - PERMISSION_GROUP_IGNORE_BATTERY_OPTIMIZATIONS, - PERMISSION_GROUP_NOTIFICATION, - PERMISSION_GROUP_ACCESS_MEDIA_LOCATION, - PERMISSION_GROUP_ACTIVITY_RECOGNITION, - PERMISSION_GROUP_UNKNOWN, - PERMISSION_GROUP_BLUETOOTH, - PERMISSION_GROUP_MANAGE_EXTERNAL_STORAGE, - PERMISSION_GROUP_SYSTEM_ALERT_WINDOW, - PERMISSION_GROUP_REQUEST_INSTALL_PACKAGES, - PERMISSION_GROUP_ACCESS_NOTIFICATION_POLICY, - PERMISSION_GROUP_BLUETOOTH_SCAN, - PERMISSION_GROUP_BLUETOOTH_ADVERTISE, - PERMISSION_GROUP_BLUETOOTH_CONNECT, - PERMISSION_GROUP_NEARBY_WIFI_DEVICES, - PERMISSION_GROUP_VIDEOS, - PERMISSION_GROUP_AUDIO, - PERMISSION_GROUP_SCHEDULE_EXACT_ALARM, - PERMISSION_GROUP_CALENDAR_WRITE_ONLY, - PERMISSION_GROUP_CALENDAR_FULL_ACCESS, - PERMISSION_GROUP_ASSISTANT, + PERMISSION_GROUP_CALENDAR, + PERMISSION_GROUP_CAMERA, + PERMISSION_GROUP_CONTACTS, + PERMISSION_GROUP_LOCATION, + PERMISSION_GROUP_LOCATION_ALWAYS, + PERMISSION_GROUP_LOCATION_WHEN_IN_USE, + PERMISSION_GROUP_MEDIA_LIBRARY, + PERMISSION_GROUP_MICROPHONE, + PERMISSION_GROUP_PHONE, + PERMISSION_GROUP_PHOTOS, + PERMISSION_GROUP_REMINDERS, + PERMISSION_GROUP_SENSORS, + PERMISSION_GROUP_SENSORS_ALWAYS, + PERMISSION_GROUP_SMS, + PERMISSION_GROUP_SPEECH, + PERMISSION_GROUP_STORAGE, + PERMISSION_GROUP_IGNORE_BATTERY_OPTIMIZATIONS, + PERMISSION_GROUP_NOTIFICATION, + PERMISSION_GROUP_ACCESS_MEDIA_LOCATION, + PERMISSION_GROUP_ACTIVITY_RECOGNITION, + PERMISSION_GROUP_UNKNOWN, + PERMISSION_GROUP_BLUETOOTH, + PERMISSION_GROUP_MANAGE_EXTERNAL_STORAGE, + PERMISSION_GROUP_SYSTEM_ALERT_WINDOW, + PERMISSION_GROUP_REQUEST_INSTALL_PACKAGES, + PERMISSION_GROUP_ACCESS_NOTIFICATION_POLICY, + PERMISSION_GROUP_BLUETOOTH_SCAN, + PERMISSION_GROUP_BLUETOOTH_ADVERTISE, + PERMISSION_GROUP_BLUETOOTH_CONNECT, + PERMISSION_GROUP_NEARBY_WIFI_DEVICES, + PERMISSION_GROUP_VIDEOS, + PERMISSION_GROUP_AUDIO, + PERMISSION_GROUP_SCHEDULE_EXACT_ALARM, + PERMISSION_GROUP_CALENDAR_WRITE_ONLY, + PERMISSION_GROUP_CALENDAR_FULL_ACCESS, + PERMISSION_GROUP_ASSISTANT, + PERMISSION_GROUP_BACKGROUND_REFRESH, + PERMISSION_GROUP_ACCESS_LOCAL_NETWORK, }) - @interface PermissionGroup { - } + @interface PermissionGroup {} //PERMISSION_STATUS static final int PERMISSION_STATUS_DENIED = 0; @@ -115,14 +116,13 @@ final class PermissionConstants { @Target(ElementType.TYPE_USE) @Retention(RetentionPolicy.SOURCE) @IntDef({ - PERMISSION_STATUS_DENIED, - PERMISSION_STATUS_GRANTED, - PERMISSION_STATUS_RESTRICTED, - PERMISSION_STATUS_LIMITED, - PERMISSION_STATUS_NEVER_ASK_AGAIN + PERMISSION_STATUS_DENIED, + PERMISSION_STATUS_GRANTED, + PERMISSION_STATUS_RESTRICTED, + PERMISSION_STATUS_LIMITED, + PERMISSION_STATUS_NEVER_ASK_AGAIN, }) - @interface PermissionStatus { - } + @interface PermissionStatus {} //SERVICE_STATUS static final int SERVICE_STATUS_DISABLED = 0; @@ -131,10 +131,9 @@ final class PermissionConstants { @Retention(RetentionPolicy.SOURCE) @IntDef({ - SERVICE_STATUS_DISABLED, - SERVICE_STATUS_ENABLED, - SERVICE_STATUS_NOT_APPLICABLE + SERVICE_STATUS_DISABLED, + SERVICE_STATUS_ENABLED, + SERVICE_STATUS_NOT_APPLICABLE, }) - @interface ServiceStatus { - } -} \ No newline at end of file + @interface ServiceStatus {} +} diff --git a/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionUtils.java b/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionUtils.java index c56bcfdfb..b9a8e0644 100644 --- a/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionUtils.java +++ b/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionUtils.java @@ -10,12 +10,10 @@ import android.os.Build; import android.os.Environment; import android.util.Log; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; import androidx.core.app.ActivityCompat; - import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -23,7 +21,9 @@ import java.util.List; public class PermissionUtils { - final static String SHARED_PREFERENCES_PERMISSION_WAS_DENIED_BEFORE_KEY = "sp_permission_handler_permission_was_denied_before"; + + static final String SHARED_PREFERENCES_PERMISSION_WAS_DENIED_BEFORE_KEY = + "sp_permission_handler_permission_was_denied_before"; @PermissionConstants.PermissionGroup static int parseManifestName(String permission) { @@ -95,45 +95,81 @@ static int parseManifestName(String permission) { return PermissionConstants.PERMISSION_GROUP_AUDIO; case Manifest.permission.SCHEDULE_EXACT_ALARM: return PermissionConstants.PERMISSION_GROUP_SCHEDULE_EXACT_ALARM; + case Manifest.permission.ACESS_LOCAL_NETWORK: + return PermissionConstants.PERMISSION_GROUP_ACCESS_LOCAL_NETWORK; default: return PermissionConstants.PERMISSION_GROUP_UNKNOWN; } } @TargetApi(22) - static List getManifestNames(Context context, @PermissionConstants.PermissionGroup int permission) { + static List getManifestNames( + Context context, + @PermissionConstants.PermissionGroup int permission + ) { final ArrayList permissionNames = new ArrayList<>(); switch (permission) { case PermissionConstants.PERMISSION_GROUP_CALENDAR_WRITE_ONLY: - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.WRITE_CALENDAR)) - permissionNames.add(Manifest.permission.WRITE_CALENDAR); + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.WRITE_CALENDAR + ) + ) permissionNames.add(Manifest.permission.WRITE_CALENDAR); break; - case PermissionConstants.PERMISSION_GROUP_CALENDAR_FULL_ACCESS: case PermissionConstants.PERMISSION_GROUP_CALENDAR: - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.WRITE_CALENDAR)) - permissionNames.add(Manifest.permission.WRITE_CALENDAR); - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.READ_CALENDAR)) - permissionNames.add(Manifest.permission.READ_CALENDAR); + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.WRITE_CALENDAR + ) + ) permissionNames.add(Manifest.permission.WRITE_CALENDAR); + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.READ_CALENDAR + ) + ) permissionNames.add(Manifest.permission.READ_CALENDAR); break; - case PermissionConstants.PERMISSION_GROUP_CAMERA: - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.CAMERA)) - permissionNames.add(Manifest.permission.CAMERA); + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.CAMERA + ) + ) permissionNames.add(Manifest.permission.CAMERA); break; - case PermissionConstants.PERMISSION_GROUP_CONTACTS: - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.READ_CONTACTS)) - permissionNames.add(Manifest.permission.READ_CONTACTS); - - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.WRITE_CONTACTS)) - permissionNames.add(Manifest.permission.WRITE_CONTACTS); - - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.GET_ACCOUNTS)) - permissionNames.add(Manifest.permission.GET_ACCOUNTS); + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.READ_CONTACTS + ) + ) permissionNames.add(Manifest.permission.READ_CONTACTS); + + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.WRITE_CONTACTS + ) + ) permissionNames.add(Manifest.permission.WRITE_CONTACTS); + + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.GET_ACCOUNTS + ) + ) permissionNames.add(Manifest.permission.GET_ACCOUNTS); break; - case PermissionConstants.PERMISSION_GROUP_LOCATION_ALWAYS: case PermissionConstants.PERMISSION_GROUP_LOCATION_WHEN_IN_USE: case PermissionConstants.PERMISSION_GROUP_LOCATION: @@ -141,150 +177,324 @@ static List getManifestNames(Context context, @PermissionConstants.Permi // case on pre Android Q devices. The ACCESS_BACKGROUND_LOCATION permission was only // introduced in Android Q, before it should be treated as the ACCESS_COARSE_LOCATION or // ACCESS_FINE_LOCATION. - if (permission == PermissionConstants.PERMISSION_GROUP_LOCATION_ALWAYS && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.ACCESS_BACKGROUND_LOCATION)) - permissionNames.add(Manifest.permission.ACCESS_BACKGROUND_LOCATION); + if ( + permission == + PermissionConstants.PERMISSION_GROUP_LOCATION_ALWAYS && + Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q + ) { + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.ACCESS_BACKGROUND_LOCATION + ) + ) permissionNames.add( + Manifest.permission.ACCESS_BACKGROUND_LOCATION + ); break; } - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.ACCESS_COARSE_LOCATION)) - permissionNames.add(Manifest.permission.ACCESS_COARSE_LOCATION); - - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.ACCESS_FINE_LOCATION)) - permissionNames.add(Manifest.permission.ACCESS_FINE_LOCATION); + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.ACCESS_COARSE_LOCATION + ) + ) permissionNames.add( + Manifest.permission.ACCESS_COARSE_LOCATION + ); + + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.ACCESS_FINE_LOCATION + ) + ) permissionNames.add(Manifest.permission.ACCESS_FINE_LOCATION); break; case PermissionConstants.PERMISSION_GROUP_SPEECH: case PermissionConstants.PERMISSION_GROUP_MICROPHONE: - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.RECORD_AUDIO)) - permissionNames.add(Manifest.permission.RECORD_AUDIO); + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.RECORD_AUDIO + ) + ) permissionNames.add(Manifest.permission.RECORD_AUDIO); break; - case PermissionConstants.PERMISSION_GROUP_PHONE: - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.READ_PHONE_STATE)) - permissionNames.add(Manifest.permission.READ_PHONE_STATE); - - if (android.os.Build.VERSION.SDK_INT > Build.VERSION_CODES.Q && hasPermissionInManifest(context, permissionNames, Manifest.permission.READ_PHONE_NUMBERS)) - permissionNames.add(Manifest.permission.READ_PHONE_NUMBERS); - - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.CALL_PHONE)) - permissionNames.add(Manifest.permission.CALL_PHONE); - - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.READ_CALL_LOG)) - permissionNames.add(Manifest.permission.READ_CALL_LOG); - - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.WRITE_CALL_LOG)) - permissionNames.add(Manifest.permission.WRITE_CALL_LOG); - - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.ADD_VOICEMAIL)) - permissionNames.add(Manifest.permission.ADD_VOICEMAIL); - - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.USE_SIP)) - permissionNames.add(Manifest.permission.USE_SIP); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && hasPermissionInManifest(context, permissionNames, Manifest.permission.ANSWER_PHONE_CALLS)) - permissionNames.add(Manifest.permission.ANSWER_PHONE_CALLS); + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.READ_PHONE_STATE + ) + ) permissionNames.add(Manifest.permission.READ_PHONE_STATE); + + if ( + android.os.Build.VERSION.SDK_INT > Build.VERSION_CODES.Q && + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.READ_PHONE_NUMBERS + ) + ) permissionNames.add(Manifest.permission.READ_PHONE_NUMBERS); + + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.CALL_PHONE + ) + ) permissionNames.add(Manifest.permission.CALL_PHONE); + + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.READ_CALL_LOG + ) + ) permissionNames.add(Manifest.permission.READ_CALL_LOG); + + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.WRITE_CALL_LOG + ) + ) permissionNames.add(Manifest.permission.WRITE_CALL_LOG); + + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.ADD_VOICEMAIL + ) + ) permissionNames.add(Manifest.permission.ADD_VOICEMAIL); + + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.USE_SIP + ) + ) permissionNames.add(Manifest.permission.USE_SIP); + + if ( + Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.ANSWER_PHONE_CALLS + ) + ) permissionNames.add(Manifest.permission.ANSWER_PHONE_CALLS); break; - case PermissionConstants.PERMISSION_GROUP_SENSORS: if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) { - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.BODY_SENSORS)) { + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.BODY_SENSORS + ) + ) { permissionNames.add(Manifest.permission.BODY_SENSORS); } } break; case PermissionConstants.PERMISSION_GROUP_SENSORS_ALWAYS: if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.BODY_SENSORS_BACKGROUND)) { - permissionNames.add(Manifest.permission.BODY_SENSORS_BACKGROUND); + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.BODY_SENSORS_BACKGROUND + ) + ) { + permissionNames.add( + Manifest.permission.BODY_SENSORS_BACKGROUND + ); } } break; case PermissionConstants.PERMISSION_GROUP_SMS: - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.SEND_SMS)) - permissionNames.add(Manifest.permission.SEND_SMS); - - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.RECEIVE_SMS)) - permissionNames.add(Manifest.permission.RECEIVE_SMS); - - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.READ_SMS)) - permissionNames.add(Manifest.permission.READ_SMS); - - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.RECEIVE_WAP_PUSH)) - permissionNames.add(Manifest.permission.RECEIVE_WAP_PUSH); - - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.RECEIVE_MMS)) - permissionNames.add(Manifest.permission.RECEIVE_MMS); + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.SEND_SMS + ) + ) permissionNames.add(Manifest.permission.SEND_SMS); + + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.RECEIVE_SMS + ) + ) permissionNames.add(Manifest.permission.RECEIVE_SMS); + + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.READ_SMS + ) + ) permissionNames.add(Manifest.permission.READ_SMS); + + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.RECEIVE_WAP_PUSH + ) + ) permissionNames.add(Manifest.permission.RECEIVE_WAP_PUSH); + + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.RECEIVE_MMS + ) + ) permissionNames.add(Manifest.permission.RECEIVE_MMS); break; - case PermissionConstants.PERMISSION_GROUP_STORAGE: - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.READ_EXTERNAL_STORAGE)) - permissionNames.add(Manifest.permission.READ_EXTERNAL_STORAGE); - - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q || (Build.VERSION.SDK_INT == Build.VERSION_CODES.Q && Environment.isExternalStorageLegacy())) { - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.WRITE_EXTERNAL_STORAGE)) - permissionNames.add(Manifest.permission.WRITE_EXTERNAL_STORAGE); + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.READ_EXTERNAL_STORAGE + ) + ) permissionNames.add( + Manifest.permission.READ_EXTERNAL_STORAGE + ); + + if ( + Build.VERSION.SDK_INT < Build.VERSION_CODES.Q || + (Build.VERSION.SDK_INT == Build.VERSION_CODES.Q && + Environment.isExternalStorageLegacy()) + ) { + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.WRITE_EXTERNAL_STORAGE + ) + ) permissionNames.add( + Manifest.permission.WRITE_EXTERNAL_STORAGE + ); break; } break; - case PermissionConstants.PERMISSION_GROUP_IGNORE_BATTERY_OPTIMIZATIONS: - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && hasPermissionInManifest(context, permissionNames, Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)) - permissionNames.add(Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS); + if ( + Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS + ) + ) permissionNames.add( + Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS + ); break; - case PermissionConstants.PERMISSION_GROUP_ACCESS_MEDIA_LOCATION: // The ACCESS_MEDIA_LOCATION permission is introduced in Android Q, meaning we should // not handle permissions on pre Android Q devices. if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) return null; - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.ACCESS_MEDIA_LOCATION)) - permissionNames.add(Manifest.permission.ACCESS_MEDIA_LOCATION); + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.ACCESS_MEDIA_LOCATION + ) + ) permissionNames.add( + Manifest.permission.ACCESS_MEDIA_LOCATION + ); break; - case PermissionConstants.PERMISSION_GROUP_ACTIVITY_RECOGNITION: // The ACTIVITY_RECOGNITION permission is introduced in Android Q, meaning we should // not handle permissions on pre Android Q devices. if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) return null; - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.ACTIVITY_RECOGNITION)) - permissionNames.add(Manifest.permission.ACTIVITY_RECOGNITION); + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.ACTIVITY_RECOGNITION + ) + ) permissionNames.add(Manifest.permission.ACTIVITY_RECOGNITION); break; - case PermissionConstants.PERMISSION_GROUP_BLUETOOTH: - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.BLUETOOTH)) - permissionNames.add(Manifest.permission.BLUETOOTH); + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.BLUETOOTH + ) + ) permissionNames.add(Manifest.permission.BLUETOOTH); break; - case PermissionConstants.PERMISSION_GROUP_MANAGE_EXTERNAL_STORAGE: // The MANAGE_EXTERNAL_STORAGE permission is introduced in Android R, meaning we should // not handle permissions on pre Android R devices. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && hasPermissionInManifest(context, permissionNames, Manifest.permission.MANAGE_EXTERNAL_STORAGE)) - permissionNames.add(Manifest.permission.MANAGE_EXTERNAL_STORAGE); + if ( + Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.MANAGE_EXTERNAL_STORAGE + ) + ) permissionNames.add( + Manifest.permission.MANAGE_EXTERNAL_STORAGE + ); break; - case PermissionConstants.PERMISSION_GROUP_SYSTEM_ALERT_WINDOW: - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.SYSTEM_ALERT_WINDOW)) - permissionNames.add(Manifest.permission.SYSTEM_ALERT_WINDOW); + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.SYSTEM_ALERT_WINDOW + ) + ) permissionNames.add(Manifest.permission.SYSTEM_ALERT_WINDOW); break; - case PermissionConstants.PERMISSION_GROUP_REQUEST_INSTALL_PACKAGES: // The REQUEST_INSTALL_PACKAGES permission is introduced in Android M, meaning we should // not handle permissions on pre Android M devices. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && hasPermissionInManifest(context, permissionNames, Manifest.permission.REQUEST_INSTALL_PACKAGES)) - permissionNames.add(Manifest.permission.REQUEST_INSTALL_PACKAGES); + if ( + Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.REQUEST_INSTALL_PACKAGES + ) + ) permissionNames.add( + Manifest.permission.REQUEST_INSTALL_PACKAGES + ); break; case PermissionConstants.PERMISSION_GROUP_ACCESS_NOTIFICATION_POLICY: // The REQUEST_NOTIFICATION_POLICY permission is introduced in Android M, meaning we should // not handle permissions on pre Android M devices. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && hasPermissionInManifest(context, permissionNames, Manifest.permission.ACCESS_NOTIFICATION_POLICY)) - permissionNames.add(Manifest.permission.ACCESS_NOTIFICATION_POLICY); + if ( + Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.ACCESS_NOTIFICATION_POLICY + ) + ) permissionNames.add( + Manifest.permission.ACCESS_NOTIFICATION_POLICY + ); break; case PermissionConstants.PERMISSION_GROUP_BLUETOOTH_SCAN: { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { // The BLUETOOTH_SCAN permission is introduced in Android S, meaning we should // not handle permissions on pre Android S devices. - String result = determineBluetoothPermission(context, Manifest.permission.BLUETOOTH_SCAN); + String result = determineBluetoothPermission( + context, + Manifest.permission.BLUETOOTH_SCAN + ); if (result != null) { permissionNames.add(result); @@ -297,7 +507,10 @@ static List getManifestNames(Context context, @PermissionConstants.Permi if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { // The BLUETOOTH_ADVERTISE permission is introduced in Android S, meaning we should // not handle permissions on pre Android S devices. - String result = determineBluetoothPermission(context, Manifest.permission.BLUETOOTH_ADVERTISE); + String result = determineBluetoothPermission( + context, + Manifest.permission.BLUETOOTH_ADVERTISE + ); if (result != null) { permissionNames.add(result); @@ -310,7 +523,10 @@ static List getManifestNames(Context context, @PermissionConstants.Permi if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { // The BLUETOOTH_CONNECT permission is introduced in Android S, meaning we should // not handle permissions on pre Android S devices. - String result = determineBluetoothPermission(context, Manifest.permission.BLUETOOTH_CONNECT); + String result = determineBluetoothPermission( + context, + Manifest.permission.BLUETOOTH_CONNECT + ); if (result != null) { permissionNames.add(result); @@ -322,40 +538,76 @@ static List getManifestNames(Context context, @PermissionConstants.Permi case PermissionConstants.PERMISSION_GROUP_NOTIFICATION: // The POST_NOTIFICATIONS permission is introduced in Android TIRAMISU, meaning we should // not handle permissions on pre Android TIRAMISU devices. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && hasPermissionInManifest(context, permissionNames, Manifest.permission.POST_NOTIFICATIONS)) - permissionNames.add(Manifest.permission.POST_NOTIFICATIONS); + if ( + Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.POST_NOTIFICATIONS + ) + ) permissionNames.add(Manifest.permission.POST_NOTIFICATIONS); break; case PermissionConstants.PERMISSION_GROUP_NEARBY_WIFI_DEVICES: // The NEARBY_WIFI_DEVICES permission is introduced in Android TIRAMISU, meaning we should // not handle permissions on pre Android TIRAMISU devices. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && hasPermissionInManifest(context, permissionNames, Manifest.permission.NEARBY_WIFI_DEVICES)) - permissionNames.add(Manifest.permission.NEARBY_WIFI_DEVICES); + if ( + Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.NEARBY_WIFI_DEVICES + ) + ) permissionNames.add(Manifest.permission.NEARBY_WIFI_DEVICES); break; case PermissionConstants.PERMISSION_GROUP_PHOTOS: // The READ_MEDIA_IMAGES permission is introduced in Android TIRAMISU, meaning we should // not handle permissions on pre Android TIRAMISU devices. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && hasPermissionInManifest(context, permissionNames, Manifest.permission.READ_MEDIA_IMAGES)) - permissionNames.add(Manifest.permission.READ_MEDIA_IMAGES); + if ( + Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.READ_MEDIA_IMAGES + ) + ) permissionNames.add(Manifest.permission.READ_MEDIA_IMAGES); break; case PermissionConstants.PERMISSION_GROUP_VIDEOS: // The READ_MEDIA_VIDEOS permission is introduced in Android TIRAMISU, meaning we should // not handle permissions on pre Android TIRAMISU devices. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && hasPermissionInManifest(context, permissionNames, Manifest.permission.READ_MEDIA_VIDEO)) - permissionNames.add(Manifest.permission.READ_MEDIA_VIDEO); + if ( + Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.READ_MEDIA_VIDEO + ) + ) permissionNames.add(Manifest.permission.READ_MEDIA_VIDEO); break; case PermissionConstants.PERMISSION_GROUP_AUDIO: // The READ_MEDIA_AUDIO permission is introduced in Android TIRAMISU, meaning we should // not handle permissions on pre Android TIRAMISU devices. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && hasPermissionInManifest(context, permissionNames, Manifest.permission.READ_MEDIA_AUDIO)) - permissionNames.add(Manifest.permission.READ_MEDIA_AUDIO); + if ( + Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.READ_MEDIA_AUDIO + ) + ) permissionNames.add(Manifest.permission.READ_MEDIA_AUDIO); break; case PermissionConstants.PERMISSION_GROUP_SCHEDULE_EXACT_ALARM: // The SCHEDULE_EXACT_ALARM permission is introduced in Android S, before Android 31 it should alway return Granted - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.SCHEDULE_EXACT_ALARM)) - permissionNames.add(Manifest.permission.SCHEDULE_EXACT_ALARM); + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.SCHEDULE_EXACT_ALARM + ) + ) permissionNames.add(Manifest.permission.SCHEDULE_EXACT_ALARM); break; case PermissionConstants.PERMISSION_GROUP_MEDIA_LIBRARY: case PermissionConstants.PERMISSION_GROUP_REMINDERS: + case PermissionConstants.PERMISSION_GROUP_ACCESS_LOCAL_NETWORK: case PermissionConstants.PERMISSION_GROUP_UNKNOWN: return null; } @@ -363,7 +615,11 @@ static List getManifestNames(Context context, @PermissionConstants.Permi return permissionNames; } - private static boolean hasPermissionInManifest(Context context, ArrayList confirmedPermissions, String permission) { + private static boolean hasPermissionInManifest( + Context context, + ArrayList confirmedPermissions, + String permission + ) { try { if (confirmedPermissions != null) { for (String r : confirmedPermissions) { @@ -374,25 +630,37 @@ private static boolean hasPermissionInManifest(Context context, ArrayList(Arrays.asList(info.requestedPermissions)); + confirmedPermissions = new ArrayList<>( + Arrays.asList(info.requestedPermissions) + ); for (String r : confirmedPermissions) { if (r.equals(permission)) { return true; } } } catch (Exception ex) { - Log.d(PermissionConstants.LOG_TAG, "Unable to check manifest for permission: ", ex); + Log.d( + PermissionConstants.LOG_TAG, + "Unable to check manifest for permission: ", + ex + ); } return false; } @@ -459,8 +727,8 @@ private static boolean hasPermissionInManifest(Context context, ArrayList statuses) { - if (statuses.contains(PermissionConstants.PERMISSION_STATUS_NEVER_ASK_AGAIN)) - return PermissionConstants.PERMISSION_STATUS_NEVER_ASK_AGAIN; - if (statuses.contains(PermissionConstants.PERMISSION_STATUS_RESTRICTED)) - return PermissionConstants.PERMISSION_STATUS_RESTRICTED; - if (statuses.contains(PermissionConstants.PERMISSION_STATUS_DENIED)) - return PermissionConstants.PERMISSION_STATUS_DENIED; - if (statuses.contains(PermissionConstants.PERMISSION_STATUS_LIMITED)) - return PermissionConstants.PERMISSION_STATUS_LIMITED; + static Integer strictestStatus( + final @NonNull Collection< + @PermissionConstants.PermissionStatus Integer + > statuses + ) { + if ( + statuses.contains( + PermissionConstants.PERMISSION_STATUS_NEVER_ASK_AGAIN + ) + ) return PermissionConstants.PERMISSION_STATUS_NEVER_ASK_AGAIN; + if ( + statuses.contains(PermissionConstants.PERMISSION_STATUS_RESTRICTED) + ) return PermissionConstants.PERMISSION_STATUS_RESTRICTED; + if ( + statuses.contains(PermissionConstants.PERMISSION_STATUS_DENIED) + ) return PermissionConstants.PERMISSION_STATUS_DENIED; + if ( + statuses.contains(PermissionConstants.PERMISSION_STATUS_LIMITED) + ) return PermissionConstants.PERMISSION_STATUS_LIMITED; return PermissionConstants.PERMISSION_STATUS_GRANTED; } @@ -486,9 +764,11 @@ static Integer strictestStatus(final @NonNull Collection<@PermissionConstants.Pe @PermissionConstants.PermissionStatus static Integer strictestStatus( final @Nullable @PermissionConstants.PermissionStatus Integer statusA, - final @Nullable @PermissionConstants.PermissionStatus Integer statusB) { - - final Collection<@PermissionConstants.PermissionStatus Integer> statuses = new HashSet<>(); + final @Nullable @PermissionConstants.PermissionStatus Integer statusB + ) { + final Collection< + @PermissionConstants.PermissionStatus Integer + > statuses = new HashSet<>(); statuses.add(statusA); statuses.add(statusB); return strictestStatus(statuses); @@ -508,8 +788,8 @@ static Integer strictestStatus( @PermissionConstants.PermissionStatus static int determineDeniedVariant( final @Nullable Activity activity, - final String permissionName) { - + final String permissionName + ) { if (activity == null) { return PermissionConstants.PERMISSION_STATUS_DENIED; } @@ -518,11 +798,15 @@ static int determineDeniedVariant( return PermissionConstants.PERMISSION_STATUS_DENIED; } - final boolean wasDeniedBefore = PermissionUtils.wasPermissionDeniedBefore(activity, permissionName); - final boolean shouldShowRational = !PermissionUtils.isNeverAskAgainSelected(activity, permissionName); + final boolean wasDeniedBefore = + PermissionUtils.wasPermissionDeniedBefore(activity, permissionName); + final boolean shouldShowRational = + !PermissionUtils.isNeverAskAgainSelected(activity, permissionName); //noinspection SimplifiableConditionalExpression - final boolean isDenied = wasDeniedBefore ? !shouldShowRational : shouldShowRational; + final boolean isDenied = wasDeniedBefore + ? !shouldShowRational + : shouldShowRational; if (!wasDeniedBefore && isDenied) { setPermissionDenied(activity, permissionName); @@ -538,24 +822,49 @@ static int determineDeniedVariant( @RequiresApi(api = Build.VERSION_CODES.M) static boolean isNeverAskAgainSelected( @NonNull final Activity activity, - final String name) { - - final boolean shouldShowRequestPermissionRationale = ActivityCompat.shouldShowRequestPermissionRationale(activity, name); + final String name + ) { + final boolean shouldShowRequestPermissionRationale = + ActivityCompat.shouldShowRequestPermissionRationale(activity, name); return !shouldShowRequestPermissionRationale; } - private static String determineBluetoothPermission(Context context, String permission) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && hasPermissionInManifest(context, null, permission)) { + private static String determineBluetoothPermission( + Context context, + String permission + ) { + if ( + Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && + hasPermissionInManifest(context, null, permission) + ) { return permission; } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { - if (hasPermissionInManifest(context, null, Manifest.permission.ACCESS_FINE_LOCATION)) { + if ( + hasPermissionInManifest( + context, + null, + Manifest.permission.ACCESS_FINE_LOCATION + ) + ) { return Manifest.permission.ACCESS_FINE_LOCATION; - } else if (hasPermissionInManifest(context, null, Manifest.permission.ACCESS_COARSE_LOCATION)) { + } else if ( + hasPermissionInManifest( + context, + null, + Manifest.permission.ACCESS_COARSE_LOCATION + ) + ) { return Manifest.permission.ACCESS_COARSE_LOCATION; } return null; - } else if (hasPermissionInManifest(context, null, Manifest.permission.ACCESS_FINE_LOCATION)) { + } else if ( + hasPermissionInManifest( + context, + null, + Manifest.permission.ACCESS_FINE_LOCATION + ) + ) { return Manifest.permission.ACCESS_FINE_LOCATION; } @@ -565,13 +874,22 @@ private static String determineBluetoothPermission(Context context, String permi // Suppress deprecation warnings since its purpose is to support to be backwards compatible with // pre TIRAMISU versions of Android @SuppressWarnings("deprecation") - private static PackageInfo getPackageInfo(Context context) throws PackageManager.NameNotFoundException { + private static PackageInfo getPackageInfo(Context context) + throws PackageManager.NameNotFoundException { final PackageManager pm = context.getPackageManager(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - return pm.getPackageInfo(context.getPackageName(), PackageManager.PackageInfoFlags.of(PackageManager.GET_PERMISSIONS)); + return pm.getPackageInfo( + context.getPackageName(), + PackageManager.PackageInfoFlags.of( + PackageManager.GET_PERMISSIONS + ) + ); } else { - return pm.getPackageInfo(context.getPackageName(), PackageManager.GET_PERMISSIONS); + return pm.getPackageInfo( + context.getPackageName(), + PackageManager.GET_PERMISSIONS + ); } } @@ -587,9 +905,16 @@ private static PackageInfo getPackageInfo(Context context) throws PackageManager * @param permissionName the name of the permission * @return whether the permission was denied in the past */ - private static boolean wasPermissionDeniedBefore(final Context context, final String permissionName) { - final SharedPreferences sharedPreferences = context.getSharedPreferences(permissionName, Context.MODE_PRIVATE); - return sharedPreferences.getBoolean(SHARED_PREFERENCES_PERMISSION_WAS_DENIED_BEFORE_KEY, false); + private static boolean wasPermissionDeniedBefore( + final Context context, + final String permissionName + ) { + final SharedPreferences sharedPreferences = + context.getSharedPreferences(permissionName, Context.MODE_PRIVATE); + return sharedPreferences.getBoolean( + SHARED_PREFERENCES_PERMISSION_WAS_DENIED_BEFORE_KEY, + false + ); } /** @@ -602,8 +927,18 @@ private static boolean wasPermissionDeniedBefore(final Context context, final St * @param context context needed for accessing shared preferences. * @param permissionName the name of the permission */ - private static void setPermissionDenied(final Context context, final String permissionName) { - final SharedPreferences sharedPreferences = context.getSharedPreferences(permissionName, Context.MODE_PRIVATE); - sharedPreferences.edit().putBoolean(SHARED_PREFERENCES_PERMISSION_WAS_DENIED_BEFORE_KEY, true).apply(); + private static void setPermissionDenied( + final Context context, + final String permissionName + ) { + final SharedPreferences sharedPreferences = + context.getSharedPreferences(permissionName, Context.MODE_PRIVATE); + sharedPreferences + .edit() + .putBoolean( + SHARED_PREFERENCES_PERMISSION_WAS_DENIED_BEFORE_KEY, + true + ) + .apply(); } } diff --git a/permission_handler_android/pubspec.yaml b/permission_handler_android/pubspec.yaml index b16ec5278..904644ec8 100644 --- a/permission_handler_android/pubspec.yaml +++ b/permission_handler_android/pubspec.yaml @@ -1,7 +1,7 @@ name: permission_handler_android description: Permission plugin for Flutter. This plugin provides the Android API to request and check permissions. homepage: https://github.com/baseflow/flutter-permission-handler -version: 13.0.1 +version: 13.0.2 environment: sdk: ^3.5.0 diff --git a/permission_handler_apple/CHANGELOG.md b/permission_handler_apple/CHANGELOG.md index fbd51929f..7f55591b5 100644 --- a/permission_handler_apple/CHANGELOG.md +++ b/permission_handler_apple/CHANGELOG.md @@ -1,3 +1,7 @@ +## 9.4.8 + +* Added support for the new Android 17 permission `ACCESS_LOCAL_NETWORK` + ## 9.4.7 * Increases minimum supported Flutter version to 3.3.0, and removes code only diff --git a/permission_handler_apple/ios/Classes/PermissionHandlerEnums.h b/permission_handler_apple/ios/Classes/PermissionHandlerEnums.h index c153dc500..69cf6620c 100644 --- a/permission_handler_apple/ios/Classes/PermissionHandlerEnums.h +++ b/permission_handler_apple/ios/Classes/PermissionHandlerEnums.h @@ -163,7 +163,8 @@ typedef NS_ENUM(int, PermissionGroup) { PermissionGroupCalendarWriteOnly, PermissionGroupCalendarFullAccess, PermissionGroupAssistant, - PermissionGroupBackgroundRefresh + PermissionGroupBackgroundRefresh, + PermissionGroupAccessLocalNetwork }; typedef NS_ENUM(int, PermissionStatus) { diff --git a/permission_handler_apple/pubspec.yaml b/permission_handler_apple/pubspec.yaml index 4abd13fb3..496e1aca6 100644 --- a/permission_handler_apple/pubspec.yaml +++ b/permission_handler_apple/pubspec.yaml @@ -2,7 +2,7 @@ name: permission_handler_apple description: Permission plugin for Flutter. This plugin provides the iOS API to request and check permissions. repository: https://github.com/baseflow/flutter-permission-handler issue_tracker: https://github.com/Baseflow/flutter-permission-handler/issues -version: 9.4.7 +version: 9.4.8 environment: sdk: ">=2.18.0 <4.0.0" diff --git a/permission_handler_html/CHANGELOG.md b/permission_handler_html/CHANGELOG.md index bfe470242..4349fbf58 100644 --- a/permission_handler_html/CHANGELOG.md +++ b/permission_handler_html/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.4+0 + +* Added support for the new Android 17 permission `ACCESS_LOCAL_NETWORK` + ## 0.1.3+5 - Updates the way how `window.navigator.mediaDevices` is accessed to keep supporting WASM. diff --git a/permission_handler_html/pubspec.yaml b/permission_handler_html/pubspec.yaml index 2b3a022e5..92d8fb40f 100644 --- a/permission_handler_html/pubspec.yaml +++ b/permission_handler_html/pubspec.yaml @@ -1,6 +1,6 @@ name: permission_handler_html description: Permission plugin for Flutter. This plugin provides the web API to request and check permissions. -version: 0.1.3+5 +version: 0.1.4+0 homepage: https://github.com/baseflow/flutter-permission-handler diff --git a/permission_handler_platform_interface/CHANGELOG.md b/permission_handler_platform_interface/CHANGELOG.md index 825a49ee8..510ff0a95 100644 --- a/permission_handler_platform_interface/CHANGELOG.md +++ b/permission_handler_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 4.3.1 + +* Added support for the new Android 17 permission `ACCESS_LOCAL_NETWORK` + ## 4.3.0 - Updates project dependencies. diff --git a/permission_handler_platform_interface/lib/src/permissions.dart b/permission_handler_platform_interface/lib/src/permissions.dart index b81a99f28..9310520cd 100644 --- a/permission_handler_platform_interface/lib/src/permissions.dart +++ b/permission_handler_platform_interface/lib/src/permissions.dart @@ -326,6 +326,11 @@ class Permission { /// Permission for reading the current background refresh status. (iOS only) static const backgroundRefresh = Permission._(39); + /// Permission for using local network protocols (broad access) + /// + /// Android 17+ (API 37+) + static const accessLocalNetwork = Permission._(40); + /// Returns a list of all possible [PermissionGroup] values. static const List values = [ // ignore: deprecated_member_use_from_same_package diff --git a/permission_handler_platform_interface/pubspec.yaml b/permission_handler_platform_interface/pubspec.yaml index 586671633..6dce893af 100644 --- a/permission_handler_platform_interface/pubspec.yaml +++ b/permission_handler_platform_interface/pubspec.yaml @@ -3,7 +3,7 @@ description: A common platform interface for the permission_handler plugin. homepage: https://github.com/baseflow/flutter-permission-handler/tree/master/permission_handler_platform_interface # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes -version: 4.3.0 +version: 4.3.1 environment: sdk: ^3.5.0 diff --git a/permission_handler_windows/CHANGELOG.md b/permission_handler_windows/CHANGELOG.md index 91c2f5049..f951b347d 100644 --- a/permission_handler_windows/CHANGELOG.md +++ b/permission_handler_windows/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.2.2 + +* Added support for the new Android 17 permission `ACCESS_LOCAL_NETWORK` + ## 0.2.1 * Updates the dependency on `permission_handler_platform_interface` to version 4.1.0 (SiriKit support is only available for iOS and macOS). diff --git a/permission_handler_windows/pubspec.yaml b/permission_handler_windows/pubspec.yaml index f5553e0d6..3495a07b7 100644 --- a/permission_handler_windows/pubspec.yaml +++ b/permission_handler_windows/pubspec.yaml @@ -1,6 +1,6 @@ name: permission_handler_windows description: Permission plugin for Flutter. This plugin provides the Windows API to request and check permissions. -version: 0.2.1 +version: 0.2.2 homepage: https://github.com/baseflow/flutter-permission-handler flutter: diff --git a/permission_handler_windows/windows/permission_constants.h b/permission_handler_windows/windows/permission_constants.h index 1bc10737c..d0c580d68 100644 --- a/permission_handler_windows/windows/permission_constants.h +++ b/permission_handler_windows/windows/permission_constants.h @@ -50,7 +50,8 @@ class PermissionConstants { CALENDAR_WRITE_ONLY = 36, CALENDAR_FULL_ACCESS = 37, ASSISTANT = 38, - BACKGROUND_REFRESH = 39 + BACKGROUND_REFRESH = 39, + ACCESS_LOCAL_NETWORK = 40, }; //PERMISSION_STATUS From 2593bec665dbd053708def2a6e9628a5287bd4d3 Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 27 May 2026 14:43:31 +0200 Subject: [PATCH 02/57] bump main package version --- permission_handler/CHANGELOG.md | 4 ++++ permission_handler/pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/permission_handler/CHANGELOG.md b/permission_handler/CHANGELOG.md index 576f07f1b..86d84043f 100644 --- a/permission_handler/CHANGELOG.md +++ b/permission_handler/CHANGELOG.md @@ -1,3 +1,7 @@ +## 12.0.2 + +* Added support for the new Android 17 permission `ACCESS_LOCAL_NETWORK` + ## 12.0.1 - Updates the correspondence between permission groups and the key values of Info.plist in the README.md. diff --git a/permission_handler/pubspec.yaml b/permission_handler/pubspec.yaml index 3e0861cd9..1c94a6d59 100644 --- a/permission_handler/pubspec.yaml +++ b/permission_handler/pubspec.yaml @@ -2,7 +2,7 @@ name: permission_handler description: Permission plugin for Flutter. This plugin provides a cross-platform (iOS, Android) API to request and check permissions. repository: https://github.com/baseflow/flutter-permission-handler issue_tracker: https://github.com/Baseflow/flutter-permission-handler/issues -version: 12.0.1 +version: 12.0.2 environment: sdk: ^3.5.0 From 5512a658f4f1860157dc9c176de7f4bad69c87d1 Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 27 May 2026 14:47:31 +0200 Subject: [PATCH 03/57] bump compilesdk version for android --- permission_handler_android/CHANGELOG.md | 4 ++++ permission_handler_android/android/build.gradle | 2 +- permission_handler_android/pubspec.yaml | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/permission_handler_android/CHANGELOG.md b/permission_handler_android/CHANGELOG.md index dd342199a..deca632fc 100644 --- a/permission_handler_android/CHANGELOG.md +++ b/permission_handler_android/CHANGELOG.md @@ -1,3 +1,7 @@ +## 13.0.3 + +* Bump compileSDK version to 37 + ## 13.0.2 * Added support for the new Android 17 permission `ACCESS_LOCAL_NETWORK` diff --git a/permission_handler_android/android/build.gradle b/permission_handler_android/android/build.gradle index fff4a308b..443882c1f 100644 --- a/permission_handler_android/android/build.gradle +++ b/permission_handler_android/android/build.gradle @@ -26,7 +26,7 @@ android { if (project.android.hasProperty("namespace")) { namespace 'com.baseflow.permissionhandler' } - compileSdkVersion 35 + compileSdkVersion 37 compileOptions { sourceCompatibility JavaVersion.VERSION_17 diff --git a/permission_handler_android/pubspec.yaml b/permission_handler_android/pubspec.yaml index 904644ec8..fb1bb8aec 100644 --- a/permission_handler_android/pubspec.yaml +++ b/permission_handler_android/pubspec.yaml @@ -1,7 +1,7 @@ name: permission_handler_android description: Permission plugin for Flutter. This plugin provides the Android API to request and check permissions. homepage: https://github.com/baseflow/flutter-permission-handler -version: 13.0.2 +version: 13.0.3 environment: sdk: ^3.5.0 From 980eaf0e4bb34b1d5555345784085662e0ac3e7e Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 27 May 2026 14:53:25 +0200 Subject: [PATCH 04/57] Updated android pakcage version to 14 (breaking) --- permission_handler/pubspec.yaml | 8 ++++---- permission_handler_android/CHANGELOG.md | 10 ++++++---- permission_handler_android/pubspec.yaml | 2 +- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/permission_handler/pubspec.yaml b/permission_handler/pubspec.yaml index 1c94a6d59..84178b205 100644 --- a/permission_handler/pubspec.yaml +++ b/permission_handler/pubspec.yaml @@ -24,11 +24,11 @@ dependencies: flutter: sdk: flutter meta: ^1.7.0 - permission_handler_android: ^13.0.0 - permission_handler_apple: ^9.4.6 + permission_handler_android: ^14.0.0 + permission_handler_apple: ^9.4.8 permission_handler_html: ^0.1.1 - permission_handler_windows: ^0.2.1 - permission_handler_platform_interface: ^4.3.0 + permission_handler_windows: ^0.2.2 + permission_handler_platform_interface: ^4.3.1 dev_dependencies: flutter_lints: ^5.0.0 diff --git a/permission_handler_android/CHANGELOG.md b/permission_handler_android/CHANGELOG.md index deca632fc..b895ea7ed 100644 --- a/permission_handler_android/CHANGELOG.md +++ b/permission_handler_android/CHANGELOG.md @@ -1,14 +1,16 @@ -## 13.0.3 +## 14.0.0 -* Bump compileSDK version to 37 +- **BREAKING CHANGES:** When updating to version 14.0.0 make sure to also set the `compileSdkVersion` in the `app/build.gradle` file to `37`. +- Updates Android `compileSdkVersion: 35` to `37` +- Bump compileSDK version to 37 ## 13.0.2 -* Added support for the new Android 17 permission `ACCESS_LOCAL_NETWORK` +- Added support for the new Android 17 permission `ACCESS_LOCAL_NETWORK` ## 13.0.1 -* fix: Resolve `PermissionRequestInProgressException` when app is relaunched with non-standard launchMode. +- fix: Resolve `PermissionRequestInProgressException` when app is relaunched with non-standard launchMode. ## 13.0.0 diff --git a/permission_handler_android/pubspec.yaml b/permission_handler_android/pubspec.yaml index fb1bb8aec..045c2247f 100644 --- a/permission_handler_android/pubspec.yaml +++ b/permission_handler_android/pubspec.yaml @@ -1,7 +1,7 @@ name: permission_handler_android description: Permission plugin for Flutter. This plugin provides the Android API to request and check permissions. homepage: https://github.com/baseflow/flutter-permission-handler -version: 13.0.3 +version: 14.0.0 environment: sdk: ^3.5.0 From 38f1e216b4e55c0c33d26466404419575a65eddc Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 27 May 2026 15:00:27 +0200 Subject: [PATCH 05/57] Just a typo --- .../java/com/baseflow/permissionhandler/PermissionUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionUtils.java b/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionUtils.java index b9a8e0644..7b5849692 100644 --- a/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionUtils.java +++ b/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionUtils.java @@ -95,7 +95,7 @@ static int parseManifestName(String permission) { return PermissionConstants.PERMISSION_GROUP_AUDIO; case Manifest.permission.SCHEDULE_EXACT_ALARM: return PermissionConstants.PERMISSION_GROUP_SCHEDULE_EXACT_ALARM; - case Manifest.permission.ACESS_LOCAL_NETWORK: + case Manifest.permission.ACCESS_LOCAL_NETWORK: return PermissionConstants.PERMISSION_GROUP_ACCESS_LOCAL_NETWORK; default: return PermissionConstants.PERMISSION_GROUP_UNKNOWN; From 8f21da5e678dd54278e14bab254c98befc5cb6b5 Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 27 May 2026 15:05:55 +0200 Subject: [PATCH 06/57] missing defs --- permission_handler/CHANGELOG.md | 3 ++- permission_handler/pubspec.yaml | 4 ++-- permission_handler_platform_interface/CHANGELOG.md | 4 ++++ .../lib/src/permissions.dart | 2 ++ permission_handler_platform_interface/pubspec.yaml | 2 +- 5 files changed, 11 insertions(+), 4 deletions(-) diff --git a/permission_handler/CHANGELOG.md b/permission_handler/CHANGELOG.md index 86d84043f..37a0a3c00 100644 --- a/permission_handler/CHANGELOG.md +++ b/permission_handler/CHANGELOG.md @@ -1,5 +1,6 @@ -## 12.0.2 +## 13.0.0 +* **BREAKING CHANGE:** , android compilesdk now set to version `compileSdkVersion 37` * Added support for the new Android 17 permission `ACCESS_LOCAL_NETWORK` ## 12.0.1 diff --git a/permission_handler/pubspec.yaml b/permission_handler/pubspec.yaml index 84178b205..716a2674f 100644 --- a/permission_handler/pubspec.yaml +++ b/permission_handler/pubspec.yaml @@ -2,7 +2,7 @@ name: permission_handler description: Permission plugin for Flutter. This plugin provides a cross-platform (iOS, Android) API to request and check permissions. repository: https://github.com/baseflow/flutter-permission-handler issue_tracker: https://github.com/Baseflow/flutter-permission-handler/issues -version: 12.0.2 +version: 13.0.0 environment: sdk: ^3.5.0 @@ -28,7 +28,7 @@ dependencies: permission_handler_apple: ^9.4.8 permission_handler_html: ^0.1.1 permission_handler_windows: ^0.2.2 - permission_handler_platform_interface: ^4.3.1 + permission_handler_platform_interface: ^4.3.2 dev_dependencies: flutter_lints: ^5.0.0 diff --git a/permission_handler_platform_interface/CHANGELOG.md b/permission_handler_platform_interface/CHANGELOG.md index 510ff0a95..a75b9f029 100644 --- a/permission_handler_platform_interface/CHANGELOG.md +++ b/permission_handler_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 4.3.2 + +* Fix support for the new Android 17 permission `ACCESS_LOCAL_NETWORK` + ## 4.3.1 * Added support for the new Android 17 permission `ACCESS_LOCAL_NETWORK` diff --git a/permission_handler_platform_interface/lib/src/permissions.dart b/permission_handler_platform_interface/lib/src/permissions.dart index 9310520cd..8eb1f743f 100644 --- a/permission_handler_platform_interface/lib/src/permissions.dart +++ b/permission_handler_platform_interface/lib/src/permissions.dart @@ -374,6 +374,7 @@ class Permission { calendarFullAccess, assistant, backgroundRefresh, + accessLocalNetwork, ]; static const List _names = [ @@ -417,6 +418,7 @@ class Permission { 'calendarFullAccess', 'assistant', 'backgroundRefresh', + 'accessLocalNetwork', ]; @override diff --git a/permission_handler_platform_interface/pubspec.yaml b/permission_handler_platform_interface/pubspec.yaml index 6dce893af..665dac0b0 100644 --- a/permission_handler_platform_interface/pubspec.yaml +++ b/permission_handler_platform_interface/pubspec.yaml @@ -3,7 +3,7 @@ description: A common platform interface for the permission_handler plugin. homepage: https://github.com/baseflow/flutter-permission-handler/tree/master/permission_handler_platform_interface # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes -version: 4.3.1 +version: 4.3.2 environment: sdk: ^3.5.0 From 5f213a48972dfb914475a3ecbb70a22a54f77824 Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 27 May 2026 15:13:21 +0200 Subject: [PATCH 07/57] ... --- permission_handler/CHANGELOG.md | 8 ++++++-- permission_handler/pubspec.yaml | 4 ++-- permission_handler_android/CHANGELOG.md | 4 ++++ permission_handler_android/pubspec.yaml | 2 +- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/permission_handler/CHANGELOG.md b/permission_handler/CHANGELOG.md index 37a0a3c00..134798ed8 100644 --- a/permission_handler/CHANGELOG.md +++ b/permission_handler/CHANGELOG.md @@ -1,7 +1,11 @@ +## 13.0.1 + +- version bump + ## 13.0.0 -* **BREAKING CHANGE:** , android compilesdk now set to version `compileSdkVersion 37` -* Added support for the new Android 17 permission `ACCESS_LOCAL_NETWORK` +- **BREAKING CHANGE:** , android compilesdk now set to version `compileSdkVersion 37` +- Added support for the new Android 17 permission `ACCESS_LOCAL_NETWORK` ## 12.0.1 diff --git a/permission_handler/pubspec.yaml b/permission_handler/pubspec.yaml index 716a2674f..7f8b93f42 100644 --- a/permission_handler/pubspec.yaml +++ b/permission_handler/pubspec.yaml @@ -2,7 +2,7 @@ name: permission_handler description: Permission plugin for Flutter. This plugin provides a cross-platform (iOS, Android) API to request and check permissions. repository: https://github.com/baseflow/flutter-permission-handler issue_tracker: https://github.com/Baseflow/flutter-permission-handler/issues -version: 13.0.0 +version: 13.0.1 environment: sdk: ^3.5.0 @@ -24,7 +24,7 @@ dependencies: flutter: sdk: flutter meta: ^1.7.0 - permission_handler_android: ^14.0.0 + permission_handler_android: ^14.0.1 permission_handler_apple: ^9.4.8 permission_handler_html: ^0.1.1 permission_handler_windows: ^0.2.2 diff --git a/permission_handler_android/CHANGELOG.md b/permission_handler_android/CHANGELOG.md index b895ea7ed..7180a5985 100644 --- a/permission_handler_android/CHANGELOG.md +++ b/permission_handler_android/CHANGELOG.md @@ -1,3 +1,7 @@ +## 14.0.1 + +- Version bump + ## 14.0.0 - **BREAKING CHANGES:** When updating to version 14.0.0 make sure to also set the `compileSdkVersion` in the `app/build.gradle` file to `37`. diff --git a/permission_handler_android/pubspec.yaml b/permission_handler_android/pubspec.yaml index 045c2247f..efd02930e 100644 --- a/permission_handler_android/pubspec.yaml +++ b/permission_handler_android/pubspec.yaml @@ -1,7 +1,7 @@ name: permission_handler_android description: Permission plugin for Flutter. This plugin provides the Android API to request and check permissions. homepage: https://github.com/baseflow/flutter-permission-handler -version: 14.0.0 +version: 14.0.1 environment: sdk: ^3.5.0 From a83e0ad3097c1cf85b721b10109836c1383ce26a Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 27 May 2026 15:19:03 +0200 Subject: [PATCH 08/57] ... --- .../permissionhandler/PermissionUtils.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionUtils.java b/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionUtils.java index 7b5849692..35cc35e2d 100644 --- a/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionUtils.java +++ b/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionUtils.java @@ -605,9 +605,21 @@ static List getManifestNames( ) ) permissionNames.add(Manifest.permission.SCHEDULE_EXACT_ALARM); break; + case PermissionConstants.PERMISSION_GROUP_ACCESS_LOCAL_NETWORK: + // The ACCESS_LOCAL_NETWORK permission is introduced in API level 37 (Cinnamon Bun) + // API 36 was allowed but only with e.g. NEARBY_WIFI_DEVICES, so we should not handle permissions on pre Android 37 devices. + // Prior to 36, this was always allowed. + if ( + Build.VERSION.SDK_INT >= Build.VERSION_CODES.CINNAMON_BUN && + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.ACCESS_LOCAL_NETWORK + ) + ) permissionNames.add(Manifest.permission.ACCESS_LOCAL_NETWORK); + break; case PermissionConstants.PERMISSION_GROUP_MEDIA_LIBRARY: case PermissionConstants.PERMISSION_GROUP_REMINDERS: - case PermissionConstants.PERMISSION_GROUP_ACCESS_LOCAL_NETWORK: case PermissionConstants.PERMISSION_GROUP_UNKNOWN: return null; } From 4d93013127f0dc89a0dc985ad323fdac5227150e Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 3 Jun 2026 10:39:13 +0200 Subject: [PATCH 09/57] Added ACCESS_LOCAL_NETWORK permission for android 17 --- permission_handler_android/CHANGELOG.md | 3 + .../PermissionConstants.java | 105 ++- .../permissionhandler/PermissionUtils.java | 659 +++++++++++++----- permission_handler_android/pubspec.yaml | 2 +- permission_handler_apple/CHANGELOG.md | 1 + .../PermissionHandlerEnums.h | 3 +- permission_handler_html/CHANGELOG.md | 4 + permission_handler_html/pubspec.yaml | 2 +- .../CHANGELOG.md | 4 + .../lib/src/permissions.dart | 5 + .../pubspec.yaml | 2 +- permission_handler_windows/CHANGELOG.md | 4 + permission_handler_windows/pubspec.yaml | 2 +- .../windows/permission_constants.h | 3 +- 14 files changed, 578 insertions(+), 221 deletions(-) diff --git a/permission_handler_android/CHANGELOG.md b/permission_handler_android/CHANGELOG.md index dfec82c83..dd342199a 100644 --- a/permission_handler_android/CHANGELOG.md +++ b/permission_handler_android/CHANGELOG.md @@ -1,3 +1,6 @@ +## 13.0.2 + +* Added support for the new Android 17 permission `ACCESS_LOCAL_NETWORK` ## 13.0.1 diff --git a/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionConstants.java b/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionConstants.java index 0262db176..734aa019f 100644 --- a/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionConstants.java +++ b/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionConstants.java @@ -1,13 +1,13 @@ package com.baseflow.permissionhandler; import androidx.annotation.IntDef; - import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; final class PermissionConstants { + static final String LOG_TAG = "permissions_handler"; static final int PERMISSION_CODE = 24; static final int PERMISSION_CODE_IGNORE_BATTERY_OPTIMIZATIONS = 209; @@ -17,7 +17,6 @@ final class PermissionConstants { static final int PERMISSION_CODE_ACCESS_NOTIFICATION_POLICY = 213; static final int PERMISSION_CODE_SCHEDULE_EXACT_ALARM = 214; - // PERMISSION_GROUP // Deprecated in favor of PERMISSION_GROUP_CALENDAR_WRITE_ONLY and @@ -62,48 +61,50 @@ final class PermissionConstants { static final int PERMISSION_GROUP_CALENDAR_FULL_ACCESS = 37; static final int PERMISSION_GROUP_ASSISTANT = 38; static final int PERMISSION_GROUP_BACKGROUND_REFRESH = 39; + static final int PERMISSION_GROUP_ACCESS_LOCAL_NETWORK = 40; @Retention(RetentionPolicy.SOURCE) @IntDef({ - PERMISSION_GROUP_CALENDAR, - PERMISSION_GROUP_CAMERA, - PERMISSION_GROUP_CONTACTS, - PERMISSION_GROUP_LOCATION, - PERMISSION_GROUP_LOCATION_ALWAYS, - PERMISSION_GROUP_LOCATION_WHEN_IN_USE, - PERMISSION_GROUP_MEDIA_LIBRARY, - PERMISSION_GROUP_MICROPHONE, - PERMISSION_GROUP_PHONE, - PERMISSION_GROUP_PHOTOS, - PERMISSION_GROUP_REMINDERS, - PERMISSION_GROUP_SENSORS, - PERMISSION_GROUP_SENSORS_ALWAYS, - PERMISSION_GROUP_SMS, - PERMISSION_GROUP_SPEECH, - PERMISSION_GROUP_STORAGE, - PERMISSION_GROUP_IGNORE_BATTERY_OPTIMIZATIONS, - PERMISSION_GROUP_NOTIFICATION, - PERMISSION_GROUP_ACCESS_MEDIA_LOCATION, - PERMISSION_GROUP_ACTIVITY_RECOGNITION, - PERMISSION_GROUP_UNKNOWN, - PERMISSION_GROUP_BLUETOOTH, - PERMISSION_GROUP_MANAGE_EXTERNAL_STORAGE, - PERMISSION_GROUP_SYSTEM_ALERT_WINDOW, - PERMISSION_GROUP_REQUEST_INSTALL_PACKAGES, - PERMISSION_GROUP_ACCESS_NOTIFICATION_POLICY, - PERMISSION_GROUP_BLUETOOTH_SCAN, - PERMISSION_GROUP_BLUETOOTH_ADVERTISE, - PERMISSION_GROUP_BLUETOOTH_CONNECT, - PERMISSION_GROUP_NEARBY_WIFI_DEVICES, - PERMISSION_GROUP_VIDEOS, - PERMISSION_GROUP_AUDIO, - PERMISSION_GROUP_SCHEDULE_EXACT_ALARM, - PERMISSION_GROUP_CALENDAR_WRITE_ONLY, - PERMISSION_GROUP_CALENDAR_FULL_ACCESS, - PERMISSION_GROUP_ASSISTANT, + PERMISSION_GROUP_CALENDAR, + PERMISSION_GROUP_CAMERA, + PERMISSION_GROUP_CONTACTS, + PERMISSION_GROUP_LOCATION, + PERMISSION_GROUP_LOCATION_ALWAYS, + PERMISSION_GROUP_LOCATION_WHEN_IN_USE, + PERMISSION_GROUP_MEDIA_LIBRARY, + PERMISSION_GROUP_MICROPHONE, + PERMISSION_GROUP_PHONE, + PERMISSION_GROUP_PHOTOS, + PERMISSION_GROUP_REMINDERS, + PERMISSION_GROUP_SENSORS, + PERMISSION_GROUP_SENSORS_ALWAYS, + PERMISSION_GROUP_SMS, + PERMISSION_GROUP_SPEECH, + PERMISSION_GROUP_STORAGE, + PERMISSION_GROUP_IGNORE_BATTERY_OPTIMIZATIONS, + PERMISSION_GROUP_NOTIFICATION, + PERMISSION_GROUP_ACCESS_MEDIA_LOCATION, + PERMISSION_GROUP_ACTIVITY_RECOGNITION, + PERMISSION_GROUP_UNKNOWN, + PERMISSION_GROUP_BLUETOOTH, + PERMISSION_GROUP_MANAGE_EXTERNAL_STORAGE, + PERMISSION_GROUP_SYSTEM_ALERT_WINDOW, + PERMISSION_GROUP_REQUEST_INSTALL_PACKAGES, + PERMISSION_GROUP_ACCESS_NOTIFICATION_POLICY, + PERMISSION_GROUP_BLUETOOTH_SCAN, + PERMISSION_GROUP_BLUETOOTH_ADVERTISE, + PERMISSION_GROUP_BLUETOOTH_CONNECT, + PERMISSION_GROUP_NEARBY_WIFI_DEVICES, + PERMISSION_GROUP_VIDEOS, + PERMISSION_GROUP_AUDIO, + PERMISSION_GROUP_SCHEDULE_EXACT_ALARM, + PERMISSION_GROUP_CALENDAR_WRITE_ONLY, + PERMISSION_GROUP_CALENDAR_FULL_ACCESS, + PERMISSION_GROUP_ASSISTANT, + PERMISSION_GROUP_BACKGROUND_REFRESH, + PERMISSION_GROUP_ACCESS_LOCAL_NETWORK, }) - @interface PermissionGroup { - } + @interface PermissionGroup {} //PERMISSION_STATUS static final int PERMISSION_STATUS_DENIED = 0; @@ -115,14 +116,13 @@ final class PermissionConstants { @Target(ElementType.TYPE_USE) @Retention(RetentionPolicy.SOURCE) @IntDef({ - PERMISSION_STATUS_DENIED, - PERMISSION_STATUS_GRANTED, - PERMISSION_STATUS_RESTRICTED, - PERMISSION_STATUS_LIMITED, - PERMISSION_STATUS_NEVER_ASK_AGAIN + PERMISSION_STATUS_DENIED, + PERMISSION_STATUS_GRANTED, + PERMISSION_STATUS_RESTRICTED, + PERMISSION_STATUS_LIMITED, + PERMISSION_STATUS_NEVER_ASK_AGAIN, }) - @interface PermissionStatus { - } + @interface PermissionStatus {} //SERVICE_STATUS static final int SERVICE_STATUS_DISABLED = 0; @@ -131,10 +131,9 @@ final class PermissionConstants { @Retention(RetentionPolicy.SOURCE) @IntDef({ - SERVICE_STATUS_DISABLED, - SERVICE_STATUS_ENABLED, - SERVICE_STATUS_NOT_APPLICABLE + SERVICE_STATUS_DISABLED, + SERVICE_STATUS_ENABLED, + SERVICE_STATUS_NOT_APPLICABLE, }) - @interface ServiceStatus { - } -} \ No newline at end of file + @interface ServiceStatus {} +} diff --git a/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionUtils.java b/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionUtils.java index c56bcfdfb..b9a8e0644 100644 --- a/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionUtils.java +++ b/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionUtils.java @@ -10,12 +10,10 @@ import android.os.Build; import android.os.Environment; import android.util.Log; - import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; import androidx.core.app.ActivityCompat; - import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -23,7 +21,9 @@ import java.util.List; public class PermissionUtils { - final static String SHARED_PREFERENCES_PERMISSION_WAS_DENIED_BEFORE_KEY = "sp_permission_handler_permission_was_denied_before"; + + static final String SHARED_PREFERENCES_PERMISSION_WAS_DENIED_BEFORE_KEY = + "sp_permission_handler_permission_was_denied_before"; @PermissionConstants.PermissionGroup static int parseManifestName(String permission) { @@ -95,45 +95,81 @@ static int parseManifestName(String permission) { return PermissionConstants.PERMISSION_GROUP_AUDIO; case Manifest.permission.SCHEDULE_EXACT_ALARM: return PermissionConstants.PERMISSION_GROUP_SCHEDULE_EXACT_ALARM; + case Manifest.permission.ACESS_LOCAL_NETWORK: + return PermissionConstants.PERMISSION_GROUP_ACCESS_LOCAL_NETWORK; default: return PermissionConstants.PERMISSION_GROUP_UNKNOWN; } } @TargetApi(22) - static List getManifestNames(Context context, @PermissionConstants.PermissionGroup int permission) { + static List getManifestNames( + Context context, + @PermissionConstants.PermissionGroup int permission + ) { final ArrayList permissionNames = new ArrayList<>(); switch (permission) { case PermissionConstants.PERMISSION_GROUP_CALENDAR_WRITE_ONLY: - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.WRITE_CALENDAR)) - permissionNames.add(Manifest.permission.WRITE_CALENDAR); + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.WRITE_CALENDAR + ) + ) permissionNames.add(Manifest.permission.WRITE_CALENDAR); break; - case PermissionConstants.PERMISSION_GROUP_CALENDAR_FULL_ACCESS: case PermissionConstants.PERMISSION_GROUP_CALENDAR: - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.WRITE_CALENDAR)) - permissionNames.add(Manifest.permission.WRITE_CALENDAR); - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.READ_CALENDAR)) - permissionNames.add(Manifest.permission.READ_CALENDAR); + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.WRITE_CALENDAR + ) + ) permissionNames.add(Manifest.permission.WRITE_CALENDAR); + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.READ_CALENDAR + ) + ) permissionNames.add(Manifest.permission.READ_CALENDAR); break; - case PermissionConstants.PERMISSION_GROUP_CAMERA: - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.CAMERA)) - permissionNames.add(Manifest.permission.CAMERA); + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.CAMERA + ) + ) permissionNames.add(Manifest.permission.CAMERA); break; - case PermissionConstants.PERMISSION_GROUP_CONTACTS: - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.READ_CONTACTS)) - permissionNames.add(Manifest.permission.READ_CONTACTS); - - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.WRITE_CONTACTS)) - permissionNames.add(Manifest.permission.WRITE_CONTACTS); - - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.GET_ACCOUNTS)) - permissionNames.add(Manifest.permission.GET_ACCOUNTS); + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.READ_CONTACTS + ) + ) permissionNames.add(Manifest.permission.READ_CONTACTS); + + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.WRITE_CONTACTS + ) + ) permissionNames.add(Manifest.permission.WRITE_CONTACTS); + + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.GET_ACCOUNTS + ) + ) permissionNames.add(Manifest.permission.GET_ACCOUNTS); break; - case PermissionConstants.PERMISSION_GROUP_LOCATION_ALWAYS: case PermissionConstants.PERMISSION_GROUP_LOCATION_WHEN_IN_USE: case PermissionConstants.PERMISSION_GROUP_LOCATION: @@ -141,150 +177,324 @@ static List getManifestNames(Context context, @PermissionConstants.Permi // case on pre Android Q devices. The ACCESS_BACKGROUND_LOCATION permission was only // introduced in Android Q, before it should be treated as the ACCESS_COARSE_LOCATION or // ACCESS_FINE_LOCATION. - if (permission == PermissionConstants.PERMISSION_GROUP_LOCATION_ALWAYS && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.ACCESS_BACKGROUND_LOCATION)) - permissionNames.add(Manifest.permission.ACCESS_BACKGROUND_LOCATION); + if ( + permission == + PermissionConstants.PERMISSION_GROUP_LOCATION_ALWAYS && + Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q + ) { + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.ACCESS_BACKGROUND_LOCATION + ) + ) permissionNames.add( + Manifest.permission.ACCESS_BACKGROUND_LOCATION + ); break; } - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.ACCESS_COARSE_LOCATION)) - permissionNames.add(Manifest.permission.ACCESS_COARSE_LOCATION); - - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.ACCESS_FINE_LOCATION)) - permissionNames.add(Manifest.permission.ACCESS_FINE_LOCATION); + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.ACCESS_COARSE_LOCATION + ) + ) permissionNames.add( + Manifest.permission.ACCESS_COARSE_LOCATION + ); + + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.ACCESS_FINE_LOCATION + ) + ) permissionNames.add(Manifest.permission.ACCESS_FINE_LOCATION); break; case PermissionConstants.PERMISSION_GROUP_SPEECH: case PermissionConstants.PERMISSION_GROUP_MICROPHONE: - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.RECORD_AUDIO)) - permissionNames.add(Manifest.permission.RECORD_AUDIO); + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.RECORD_AUDIO + ) + ) permissionNames.add(Manifest.permission.RECORD_AUDIO); break; - case PermissionConstants.PERMISSION_GROUP_PHONE: - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.READ_PHONE_STATE)) - permissionNames.add(Manifest.permission.READ_PHONE_STATE); - - if (android.os.Build.VERSION.SDK_INT > Build.VERSION_CODES.Q && hasPermissionInManifest(context, permissionNames, Manifest.permission.READ_PHONE_NUMBERS)) - permissionNames.add(Manifest.permission.READ_PHONE_NUMBERS); - - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.CALL_PHONE)) - permissionNames.add(Manifest.permission.CALL_PHONE); - - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.READ_CALL_LOG)) - permissionNames.add(Manifest.permission.READ_CALL_LOG); - - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.WRITE_CALL_LOG)) - permissionNames.add(Manifest.permission.WRITE_CALL_LOG); - - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.ADD_VOICEMAIL)) - permissionNames.add(Manifest.permission.ADD_VOICEMAIL); - - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.USE_SIP)) - permissionNames.add(Manifest.permission.USE_SIP); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && hasPermissionInManifest(context, permissionNames, Manifest.permission.ANSWER_PHONE_CALLS)) - permissionNames.add(Manifest.permission.ANSWER_PHONE_CALLS); + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.READ_PHONE_STATE + ) + ) permissionNames.add(Manifest.permission.READ_PHONE_STATE); + + if ( + android.os.Build.VERSION.SDK_INT > Build.VERSION_CODES.Q && + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.READ_PHONE_NUMBERS + ) + ) permissionNames.add(Manifest.permission.READ_PHONE_NUMBERS); + + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.CALL_PHONE + ) + ) permissionNames.add(Manifest.permission.CALL_PHONE); + + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.READ_CALL_LOG + ) + ) permissionNames.add(Manifest.permission.READ_CALL_LOG); + + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.WRITE_CALL_LOG + ) + ) permissionNames.add(Manifest.permission.WRITE_CALL_LOG); + + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.ADD_VOICEMAIL + ) + ) permissionNames.add(Manifest.permission.ADD_VOICEMAIL); + + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.USE_SIP + ) + ) permissionNames.add(Manifest.permission.USE_SIP); + + if ( + Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.ANSWER_PHONE_CALLS + ) + ) permissionNames.add(Manifest.permission.ANSWER_PHONE_CALLS); break; - case PermissionConstants.PERMISSION_GROUP_SENSORS: if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) { - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.BODY_SENSORS)) { + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.BODY_SENSORS + ) + ) { permissionNames.add(Manifest.permission.BODY_SENSORS); } } break; case PermissionConstants.PERMISSION_GROUP_SENSORS_ALWAYS: if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.BODY_SENSORS_BACKGROUND)) { - permissionNames.add(Manifest.permission.BODY_SENSORS_BACKGROUND); + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.BODY_SENSORS_BACKGROUND + ) + ) { + permissionNames.add( + Manifest.permission.BODY_SENSORS_BACKGROUND + ); } } break; case PermissionConstants.PERMISSION_GROUP_SMS: - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.SEND_SMS)) - permissionNames.add(Manifest.permission.SEND_SMS); - - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.RECEIVE_SMS)) - permissionNames.add(Manifest.permission.RECEIVE_SMS); - - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.READ_SMS)) - permissionNames.add(Manifest.permission.READ_SMS); - - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.RECEIVE_WAP_PUSH)) - permissionNames.add(Manifest.permission.RECEIVE_WAP_PUSH); - - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.RECEIVE_MMS)) - permissionNames.add(Manifest.permission.RECEIVE_MMS); + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.SEND_SMS + ) + ) permissionNames.add(Manifest.permission.SEND_SMS); + + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.RECEIVE_SMS + ) + ) permissionNames.add(Manifest.permission.RECEIVE_SMS); + + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.READ_SMS + ) + ) permissionNames.add(Manifest.permission.READ_SMS); + + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.RECEIVE_WAP_PUSH + ) + ) permissionNames.add(Manifest.permission.RECEIVE_WAP_PUSH); + + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.RECEIVE_MMS + ) + ) permissionNames.add(Manifest.permission.RECEIVE_MMS); break; - case PermissionConstants.PERMISSION_GROUP_STORAGE: - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.READ_EXTERNAL_STORAGE)) - permissionNames.add(Manifest.permission.READ_EXTERNAL_STORAGE); - - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q || (Build.VERSION.SDK_INT == Build.VERSION_CODES.Q && Environment.isExternalStorageLegacy())) { - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.WRITE_EXTERNAL_STORAGE)) - permissionNames.add(Manifest.permission.WRITE_EXTERNAL_STORAGE); + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.READ_EXTERNAL_STORAGE + ) + ) permissionNames.add( + Manifest.permission.READ_EXTERNAL_STORAGE + ); + + if ( + Build.VERSION.SDK_INT < Build.VERSION_CODES.Q || + (Build.VERSION.SDK_INT == Build.VERSION_CODES.Q && + Environment.isExternalStorageLegacy()) + ) { + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.WRITE_EXTERNAL_STORAGE + ) + ) permissionNames.add( + Manifest.permission.WRITE_EXTERNAL_STORAGE + ); break; } break; - case PermissionConstants.PERMISSION_GROUP_IGNORE_BATTERY_OPTIMIZATIONS: - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && hasPermissionInManifest(context, permissionNames, Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS)) - permissionNames.add(Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS); + if ( + Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS + ) + ) permissionNames.add( + Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS + ); break; - case PermissionConstants.PERMISSION_GROUP_ACCESS_MEDIA_LOCATION: // The ACCESS_MEDIA_LOCATION permission is introduced in Android Q, meaning we should // not handle permissions on pre Android Q devices. if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) return null; - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.ACCESS_MEDIA_LOCATION)) - permissionNames.add(Manifest.permission.ACCESS_MEDIA_LOCATION); + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.ACCESS_MEDIA_LOCATION + ) + ) permissionNames.add( + Manifest.permission.ACCESS_MEDIA_LOCATION + ); break; - case PermissionConstants.PERMISSION_GROUP_ACTIVITY_RECOGNITION: // The ACTIVITY_RECOGNITION permission is introduced in Android Q, meaning we should // not handle permissions on pre Android Q devices. if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) return null; - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.ACTIVITY_RECOGNITION)) - permissionNames.add(Manifest.permission.ACTIVITY_RECOGNITION); + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.ACTIVITY_RECOGNITION + ) + ) permissionNames.add(Manifest.permission.ACTIVITY_RECOGNITION); break; - case PermissionConstants.PERMISSION_GROUP_BLUETOOTH: - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.BLUETOOTH)) - permissionNames.add(Manifest.permission.BLUETOOTH); + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.BLUETOOTH + ) + ) permissionNames.add(Manifest.permission.BLUETOOTH); break; - case PermissionConstants.PERMISSION_GROUP_MANAGE_EXTERNAL_STORAGE: // The MANAGE_EXTERNAL_STORAGE permission is introduced in Android R, meaning we should // not handle permissions on pre Android R devices. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && hasPermissionInManifest(context, permissionNames, Manifest.permission.MANAGE_EXTERNAL_STORAGE)) - permissionNames.add(Manifest.permission.MANAGE_EXTERNAL_STORAGE); + if ( + Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.MANAGE_EXTERNAL_STORAGE + ) + ) permissionNames.add( + Manifest.permission.MANAGE_EXTERNAL_STORAGE + ); break; - case PermissionConstants.PERMISSION_GROUP_SYSTEM_ALERT_WINDOW: - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.SYSTEM_ALERT_WINDOW)) - permissionNames.add(Manifest.permission.SYSTEM_ALERT_WINDOW); + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.SYSTEM_ALERT_WINDOW + ) + ) permissionNames.add(Manifest.permission.SYSTEM_ALERT_WINDOW); break; - case PermissionConstants.PERMISSION_GROUP_REQUEST_INSTALL_PACKAGES: // The REQUEST_INSTALL_PACKAGES permission is introduced in Android M, meaning we should // not handle permissions on pre Android M devices. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && hasPermissionInManifest(context, permissionNames, Manifest.permission.REQUEST_INSTALL_PACKAGES)) - permissionNames.add(Manifest.permission.REQUEST_INSTALL_PACKAGES); + if ( + Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.REQUEST_INSTALL_PACKAGES + ) + ) permissionNames.add( + Manifest.permission.REQUEST_INSTALL_PACKAGES + ); break; case PermissionConstants.PERMISSION_GROUP_ACCESS_NOTIFICATION_POLICY: // The REQUEST_NOTIFICATION_POLICY permission is introduced in Android M, meaning we should // not handle permissions on pre Android M devices. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && hasPermissionInManifest(context, permissionNames, Manifest.permission.ACCESS_NOTIFICATION_POLICY)) - permissionNames.add(Manifest.permission.ACCESS_NOTIFICATION_POLICY); + if ( + Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.ACCESS_NOTIFICATION_POLICY + ) + ) permissionNames.add( + Manifest.permission.ACCESS_NOTIFICATION_POLICY + ); break; case PermissionConstants.PERMISSION_GROUP_BLUETOOTH_SCAN: { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { // The BLUETOOTH_SCAN permission is introduced in Android S, meaning we should // not handle permissions on pre Android S devices. - String result = determineBluetoothPermission(context, Manifest.permission.BLUETOOTH_SCAN); + String result = determineBluetoothPermission( + context, + Manifest.permission.BLUETOOTH_SCAN + ); if (result != null) { permissionNames.add(result); @@ -297,7 +507,10 @@ static List getManifestNames(Context context, @PermissionConstants.Permi if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { // The BLUETOOTH_ADVERTISE permission is introduced in Android S, meaning we should // not handle permissions on pre Android S devices. - String result = determineBluetoothPermission(context, Manifest.permission.BLUETOOTH_ADVERTISE); + String result = determineBluetoothPermission( + context, + Manifest.permission.BLUETOOTH_ADVERTISE + ); if (result != null) { permissionNames.add(result); @@ -310,7 +523,10 @@ static List getManifestNames(Context context, @PermissionConstants.Permi if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { // The BLUETOOTH_CONNECT permission is introduced in Android S, meaning we should // not handle permissions on pre Android S devices. - String result = determineBluetoothPermission(context, Manifest.permission.BLUETOOTH_CONNECT); + String result = determineBluetoothPermission( + context, + Manifest.permission.BLUETOOTH_CONNECT + ); if (result != null) { permissionNames.add(result); @@ -322,40 +538,76 @@ static List getManifestNames(Context context, @PermissionConstants.Permi case PermissionConstants.PERMISSION_GROUP_NOTIFICATION: // The POST_NOTIFICATIONS permission is introduced in Android TIRAMISU, meaning we should // not handle permissions on pre Android TIRAMISU devices. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && hasPermissionInManifest(context, permissionNames, Manifest.permission.POST_NOTIFICATIONS)) - permissionNames.add(Manifest.permission.POST_NOTIFICATIONS); + if ( + Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.POST_NOTIFICATIONS + ) + ) permissionNames.add(Manifest.permission.POST_NOTIFICATIONS); break; case PermissionConstants.PERMISSION_GROUP_NEARBY_WIFI_DEVICES: // The NEARBY_WIFI_DEVICES permission is introduced in Android TIRAMISU, meaning we should // not handle permissions on pre Android TIRAMISU devices. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && hasPermissionInManifest(context, permissionNames, Manifest.permission.NEARBY_WIFI_DEVICES)) - permissionNames.add(Manifest.permission.NEARBY_WIFI_DEVICES); + if ( + Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.NEARBY_WIFI_DEVICES + ) + ) permissionNames.add(Manifest.permission.NEARBY_WIFI_DEVICES); break; case PermissionConstants.PERMISSION_GROUP_PHOTOS: // The READ_MEDIA_IMAGES permission is introduced in Android TIRAMISU, meaning we should // not handle permissions on pre Android TIRAMISU devices. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && hasPermissionInManifest(context, permissionNames, Manifest.permission.READ_MEDIA_IMAGES)) - permissionNames.add(Manifest.permission.READ_MEDIA_IMAGES); + if ( + Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.READ_MEDIA_IMAGES + ) + ) permissionNames.add(Manifest.permission.READ_MEDIA_IMAGES); break; case PermissionConstants.PERMISSION_GROUP_VIDEOS: // The READ_MEDIA_VIDEOS permission is introduced in Android TIRAMISU, meaning we should // not handle permissions on pre Android TIRAMISU devices. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && hasPermissionInManifest(context, permissionNames, Manifest.permission.READ_MEDIA_VIDEO)) - permissionNames.add(Manifest.permission.READ_MEDIA_VIDEO); + if ( + Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.READ_MEDIA_VIDEO + ) + ) permissionNames.add(Manifest.permission.READ_MEDIA_VIDEO); break; case PermissionConstants.PERMISSION_GROUP_AUDIO: // The READ_MEDIA_AUDIO permission is introduced in Android TIRAMISU, meaning we should // not handle permissions on pre Android TIRAMISU devices. - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && hasPermissionInManifest(context, permissionNames, Manifest.permission.READ_MEDIA_AUDIO)) - permissionNames.add(Manifest.permission.READ_MEDIA_AUDIO); + if ( + Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU && + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.READ_MEDIA_AUDIO + ) + ) permissionNames.add(Manifest.permission.READ_MEDIA_AUDIO); break; case PermissionConstants.PERMISSION_GROUP_SCHEDULE_EXACT_ALARM: // The SCHEDULE_EXACT_ALARM permission is introduced in Android S, before Android 31 it should alway return Granted - if (hasPermissionInManifest(context, permissionNames, Manifest.permission.SCHEDULE_EXACT_ALARM)) - permissionNames.add(Manifest.permission.SCHEDULE_EXACT_ALARM); + if ( + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.SCHEDULE_EXACT_ALARM + ) + ) permissionNames.add(Manifest.permission.SCHEDULE_EXACT_ALARM); break; case PermissionConstants.PERMISSION_GROUP_MEDIA_LIBRARY: case PermissionConstants.PERMISSION_GROUP_REMINDERS: + case PermissionConstants.PERMISSION_GROUP_ACCESS_LOCAL_NETWORK: case PermissionConstants.PERMISSION_GROUP_UNKNOWN: return null; } @@ -363,7 +615,11 @@ static List getManifestNames(Context context, @PermissionConstants.Permi return permissionNames; } - private static boolean hasPermissionInManifest(Context context, ArrayList confirmedPermissions, String permission) { + private static boolean hasPermissionInManifest( + Context context, + ArrayList confirmedPermissions, + String permission + ) { try { if (confirmedPermissions != null) { for (String r : confirmedPermissions) { @@ -374,25 +630,37 @@ private static boolean hasPermissionInManifest(Context context, ArrayList(Arrays.asList(info.requestedPermissions)); + confirmedPermissions = new ArrayList<>( + Arrays.asList(info.requestedPermissions) + ); for (String r : confirmedPermissions) { if (r.equals(permission)) { return true; } } } catch (Exception ex) { - Log.d(PermissionConstants.LOG_TAG, "Unable to check manifest for permission: ", ex); + Log.d( + PermissionConstants.LOG_TAG, + "Unable to check manifest for permission: ", + ex + ); } return false; } @@ -459,8 +727,8 @@ private static boolean hasPermissionInManifest(Context context, ArrayList statuses) { - if (statuses.contains(PermissionConstants.PERMISSION_STATUS_NEVER_ASK_AGAIN)) - return PermissionConstants.PERMISSION_STATUS_NEVER_ASK_AGAIN; - if (statuses.contains(PermissionConstants.PERMISSION_STATUS_RESTRICTED)) - return PermissionConstants.PERMISSION_STATUS_RESTRICTED; - if (statuses.contains(PermissionConstants.PERMISSION_STATUS_DENIED)) - return PermissionConstants.PERMISSION_STATUS_DENIED; - if (statuses.contains(PermissionConstants.PERMISSION_STATUS_LIMITED)) - return PermissionConstants.PERMISSION_STATUS_LIMITED; + static Integer strictestStatus( + final @NonNull Collection< + @PermissionConstants.PermissionStatus Integer + > statuses + ) { + if ( + statuses.contains( + PermissionConstants.PERMISSION_STATUS_NEVER_ASK_AGAIN + ) + ) return PermissionConstants.PERMISSION_STATUS_NEVER_ASK_AGAIN; + if ( + statuses.contains(PermissionConstants.PERMISSION_STATUS_RESTRICTED) + ) return PermissionConstants.PERMISSION_STATUS_RESTRICTED; + if ( + statuses.contains(PermissionConstants.PERMISSION_STATUS_DENIED) + ) return PermissionConstants.PERMISSION_STATUS_DENIED; + if ( + statuses.contains(PermissionConstants.PERMISSION_STATUS_LIMITED) + ) return PermissionConstants.PERMISSION_STATUS_LIMITED; return PermissionConstants.PERMISSION_STATUS_GRANTED; } @@ -486,9 +764,11 @@ static Integer strictestStatus(final @NonNull Collection<@PermissionConstants.Pe @PermissionConstants.PermissionStatus static Integer strictestStatus( final @Nullable @PermissionConstants.PermissionStatus Integer statusA, - final @Nullable @PermissionConstants.PermissionStatus Integer statusB) { - - final Collection<@PermissionConstants.PermissionStatus Integer> statuses = new HashSet<>(); + final @Nullable @PermissionConstants.PermissionStatus Integer statusB + ) { + final Collection< + @PermissionConstants.PermissionStatus Integer + > statuses = new HashSet<>(); statuses.add(statusA); statuses.add(statusB); return strictestStatus(statuses); @@ -508,8 +788,8 @@ static Integer strictestStatus( @PermissionConstants.PermissionStatus static int determineDeniedVariant( final @Nullable Activity activity, - final String permissionName) { - + final String permissionName + ) { if (activity == null) { return PermissionConstants.PERMISSION_STATUS_DENIED; } @@ -518,11 +798,15 @@ static int determineDeniedVariant( return PermissionConstants.PERMISSION_STATUS_DENIED; } - final boolean wasDeniedBefore = PermissionUtils.wasPermissionDeniedBefore(activity, permissionName); - final boolean shouldShowRational = !PermissionUtils.isNeverAskAgainSelected(activity, permissionName); + final boolean wasDeniedBefore = + PermissionUtils.wasPermissionDeniedBefore(activity, permissionName); + final boolean shouldShowRational = + !PermissionUtils.isNeverAskAgainSelected(activity, permissionName); //noinspection SimplifiableConditionalExpression - final boolean isDenied = wasDeniedBefore ? !shouldShowRational : shouldShowRational; + final boolean isDenied = wasDeniedBefore + ? !shouldShowRational + : shouldShowRational; if (!wasDeniedBefore && isDenied) { setPermissionDenied(activity, permissionName); @@ -538,24 +822,49 @@ static int determineDeniedVariant( @RequiresApi(api = Build.VERSION_CODES.M) static boolean isNeverAskAgainSelected( @NonNull final Activity activity, - final String name) { - - final boolean shouldShowRequestPermissionRationale = ActivityCompat.shouldShowRequestPermissionRationale(activity, name); + final String name + ) { + final boolean shouldShowRequestPermissionRationale = + ActivityCompat.shouldShowRequestPermissionRationale(activity, name); return !shouldShowRequestPermissionRationale; } - private static String determineBluetoothPermission(Context context, String permission) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && hasPermissionInManifest(context, null, permission)) { + private static String determineBluetoothPermission( + Context context, + String permission + ) { + if ( + Build.VERSION.SDK_INT >= Build.VERSION_CODES.S && + hasPermissionInManifest(context, null, permission) + ) { return permission; } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { - if (hasPermissionInManifest(context, null, Manifest.permission.ACCESS_FINE_LOCATION)) { + if ( + hasPermissionInManifest( + context, + null, + Manifest.permission.ACCESS_FINE_LOCATION + ) + ) { return Manifest.permission.ACCESS_FINE_LOCATION; - } else if (hasPermissionInManifest(context, null, Manifest.permission.ACCESS_COARSE_LOCATION)) { + } else if ( + hasPermissionInManifest( + context, + null, + Manifest.permission.ACCESS_COARSE_LOCATION + ) + ) { return Manifest.permission.ACCESS_COARSE_LOCATION; } return null; - } else if (hasPermissionInManifest(context, null, Manifest.permission.ACCESS_FINE_LOCATION)) { + } else if ( + hasPermissionInManifest( + context, + null, + Manifest.permission.ACCESS_FINE_LOCATION + ) + ) { return Manifest.permission.ACCESS_FINE_LOCATION; } @@ -565,13 +874,22 @@ private static String determineBluetoothPermission(Context context, String permi // Suppress deprecation warnings since its purpose is to support to be backwards compatible with // pre TIRAMISU versions of Android @SuppressWarnings("deprecation") - private static PackageInfo getPackageInfo(Context context) throws PackageManager.NameNotFoundException { + private static PackageInfo getPackageInfo(Context context) + throws PackageManager.NameNotFoundException { final PackageManager pm = context.getPackageManager(); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - return pm.getPackageInfo(context.getPackageName(), PackageManager.PackageInfoFlags.of(PackageManager.GET_PERMISSIONS)); + return pm.getPackageInfo( + context.getPackageName(), + PackageManager.PackageInfoFlags.of( + PackageManager.GET_PERMISSIONS + ) + ); } else { - return pm.getPackageInfo(context.getPackageName(), PackageManager.GET_PERMISSIONS); + return pm.getPackageInfo( + context.getPackageName(), + PackageManager.GET_PERMISSIONS + ); } } @@ -587,9 +905,16 @@ private static PackageInfo getPackageInfo(Context context) throws PackageManager * @param permissionName the name of the permission * @return whether the permission was denied in the past */ - private static boolean wasPermissionDeniedBefore(final Context context, final String permissionName) { - final SharedPreferences sharedPreferences = context.getSharedPreferences(permissionName, Context.MODE_PRIVATE); - return sharedPreferences.getBoolean(SHARED_PREFERENCES_PERMISSION_WAS_DENIED_BEFORE_KEY, false); + private static boolean wasPermissionDeniedBefore( + final Context context, + final String permissionName + ) { + final SharedPreferences sharedPreferences = + context.getSharedPreferences(permissionName, Context.MODE_PRIVATE); + return sharedPreferences.getBoolean( + SHARED_PREFERENCES_PERMISSION_WAS_DENIED_BEFORE_KEY, + false + ); } /** @@ -602,8 +927,18 @@ private static boolean wasPermissionDeniedBefore(final Context context, final St * @param context context needed for accessing shared preferences. * @param permissionName the name of the permission */ - private static void setPermissionDenied(final Context context, final String permissionName) { - final SharedPreferences sharedPreferences = context.getSharedPreferences(permissionName, Context.MODE_PRIVATE); - sharedPreferences.edit().putBoolean(SHARED_PREFERENCES_PERMISSION_WAS_DENIED_BEFORE_KEY, true).apply(); + private static void setPermissionDenied( + final Context context, + final String permissionName + ) { + final SharedPreferences sharedPreferences = + context.getSharedPreferences(permissionName, Context.MODE_PRIVATE); + sharedPreferences + .edit() + .putBoolean( + SHARED_PREFERENCES_PERMISSION_WAS_DENIED_BEFORE_KEY, + true + ) + .apply(); } } diff --git a/permission_handler_android/pubspec.yaml b/permission_handler_android/pubspec.yaml index b16ec5278..904644ec8 100644 --- a/permission_handler_android/pubspec.yaml +++ b/permission_handler_android/pubspec.yaml @@ -1,7 +1,7 @@ name: permission_handler_android description: Permission plugin for Flutter. This plugin provides the Android API to request and check permissions. homepage: https://github.com/baseflow/flutter-permission-handler -version: 13.0.1 +version: 13.0.2 environment: sdk: ^3.5.0 diff --git a/permission_handler_apple/CHANGELOG.md b/permission_handler_apple/CHANGELOG.md index f60ecef2a..ace8017b1 100644 --- a/permission_handler_apple/CHANGELOG.md +++ b/permission_handler_apple/CHANGELOG.md @@ -1,6 +1,7 @@ ## 9.4.9 * Rewrites copyleft code from stackoverflow to fix compliance issue. +* Added support for the new Android 17 permission `ACCESS_LOCAL_NETWORK` ## 9.4.8 diff --git a/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/PermissionHandlerEnums.h b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/PermissionHandlerEnums.h index c153dc500..69cf6620c 100644 --- a/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/PermissionHandlerEnums.h +++ b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/PermissionHandlerEnums.h @@ -163,7 +163,8 @@ typedef NS_ENUM(int, PermissionGroup) { PermissionGroupCalendarWriteOnly, PermissionGroupCalendarFullAccess, PermissionGroupAssistant, - PermissionGroupBackgroundRefresh + PermissionGroupBackgroundRefresh, + PermissionGroupAccessLocalNetwork }; typedef NS_ENUM(int, PermissionStatus) { diff --git a/permission_handler_html/CHANGELOG.md b/permission_handler_html/CHANGELOG.md index bfe470242..4349fbf58 100644 --- a/permission_handler_html/CHANGELOG.md +++ b/permission_handler_html/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.4+0 + +* Added support for the new Android 17 permission `ACCESS_LOCAL_NETWORK` + ## 0.1.3+5 - Updates the way how `window.navigator.mediaDevices` is accessed to keep supporting WASM. diff --git a/permission_handler_html/pubspec.yaml b/permission_handler_html/pubspec.yaml index 2b3a022e5..92d8fb40f 100644 --- a/permission_handler_html/pubspec.yaml +++ b/permission_handler_html/pubspec.yaml @@ -1,6 +1,6 @@ name: permission_handler_html description: Permission plugin for Flutter. This plugin provides the web API to request and check permissions. -version: 0.1.3+5 +version: 0.1.4+0 homepage: https://github.com/baseflow/flutter-permission-handler diff --git a/permission_handler_platform_interface/CHANGELOG.md b/permission_handler_platform_interface/CHANGELOG.md index 825a49ee8..510ff0a95 100644 --- a/permission_handler_platform_interface/CHANGELOG.md +++ b/permission_handler_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 4.3.1 + +* Added support for the new Android 17 permission `ACCESS_LOCAL_NETWORK` + ## 4.3.0 - Updates project dependencies. diff --git a/permission_handler_platform_interface/lib/src/permissions.dart b/permission_handler_platform_interface/lib/src/permissions.dart index b81a99f28..9310520cd 100644 --- a/permission_handler_platform_interface/lib/src/permissions.dart +++ b/permission_handler_platform_interface/lib/src/permissions.dart @@ -326,6 +326,11 @@ class Permission { /// Permission for reading the current background refresh status. (iOS only) static const backgroundRefresh = Permission._(39); + /// Permission for using local network protocols (broad access) + /// + /// Android 17+ (API 37+) + static const accessLocalNetwork = Permission._(40); + /// Returns a list of all possible [PermissionGroup] values. static const List values = [ // ignore: deprecated_member_use_from_same_package diff --git a/permission_handler_platform_interface/pubspec.yaml b/permission_handler_platform_interface/pubspec.yaml index 586671633..6dce893af 100644 --- a/permission_handler_platform_interface/pubspec.yaml +++ b/permission_handler_platform_interface/pubspec.yaml @@ -3,7 +3,7 @@ description: A common platform interface for the permission_handler plugin. homepage: https://github.com/baseflow/flutter-permission-handler/tree/master/permission_handler_platform_interface # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes -version: 4.3.0 +version: 4.3.1 environment: sdk: ^3.5.0 diff --git a/permission_handler_windows/CHANGELOG.md b/permission_handler_windows/CHANGELOG.md index 91c2f5049..f951b347d 100644 --- a/permission_handler_windows/CHANGELOG.md +++ b/permission_handler_windows/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.2.2 + +* Added support for the new Android 17 permission `ACCESS_LOCAL_NETWORK` + ## 0.2.1 * Updates the dependency on `permission_handler_platform_interface` to version 4.1.0 (SiriKit support is only available for iOS and macOS). diff --git a/permission_handler_windows/pubspec.yaml b/permission_handler_windows/pubspec.yaml index f5553e0d6..3495a07b7 100644 --- a/permission_handler_windows/pubspec.yaml +++ b/permission_handler_windows/pubspec.yaml @@ -1,6 +1,6 @@ name: permission_handler_windows description: Permission plugin for Flutter. This plugin provides the Windows API to request and check permissions. -version: 0.2.1 +version: 0.2.2 homepage: https://github.com/baseflow/flutter-permission-handler flutter: diff --git a/permission_handler_windows/windows/permission_constants.h b/permission_handler_windows/windows/permission_constants.h index 1bc10737c..d0c580d68 100644 --- a/permission_handler_windows/windows/permission_constants.h +++ b/permission_handler_windows/windows/permission_constants.h @@ -50,7 +50,8 @@ class PermissionConstants { CALENDAR_WRITE_ONLY = 36, CALENDAR_FULL_ACCESS = 37, ASSISTANT = 38, - BACKGROUND_REFRESH = 39 + BACKGROUND_REFRESH = 39, + ACCESS_LOCAL_NETWORK = 40, }; //PERMISSION_STATUS From 5fd825e2f7cc0e3c50891fb00e6c5cfb28c21170 Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 3 Jun 2026 10:40:23 +0200 Subject: [PATCH 10/57] bump main package version --- permission_handler/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/permission_handler/CHANGELOG.md b/permission_handler/CHANGELOG.md index e44cb8f14..4d08ef4ef 100644 --- a/permission_handler/CHANGELOG.md +++ b/permission_handler/CHANGELOG.md @@ -6,6 +6,7 @@ ## 12.0.2 - Updates the documentation to include instructions on Swift Package Manager (SPM) support. +- Added support for the new Android 17 permission `ACCESS_LOCAL_NETWORK` ## 12.0.1 From 5dd7467e9cfdac5eb38980a510168bdbc776dd5f Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 27 May 2026 14:47:31 +0200 Subject: [PATCH 11/57] bump compilesdk version for android --- permission_handler_android/CHANGELOG.md | 4 ++++ permission_handler_android/android/build.gradle | 2 +- permission_handler_android/pubspec.yaml | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/permission_handler_android/CHANGELOG.md b/permission_handler_android/CHANGELOG.md index dd342199a..deca632fc 100644 --- a/permission_handler_android/CHANGELOG.md +++ b/permission_handler_android/CHANGELOG.md @@ -1,3 +1,7 @@ +## 13.0.3 + +* Bump compileSDK version to 37 + ## 13.0.2 * Added support for the new Android 17 permission `ACCESS_LOCAL_NETWORK` diff --git a/permission_handler_android/android/build.gradle b/permission_handler_android/android/build.gradle index fff4a308b..443882c1f 100644 --- a/permission_handler_android/android/build.gradle +++ b/permission_handler_android/android/build.gradle @@ -26,7 +26,7 @@ android { if (project.android.hasProperty("namespace")) { namespace 'com.baseflow.permissionhandler' } - compileSdkVersion 35 + compileSdkVersion 37 compileOptions { sourceCompatibility JavaVersion.VERSION_17 diff --git a/permission_handler_android/pubspec.yaml b/permission_handler_android/pubspec.yaml index 904644ec8..fb1bb8aec 100644 --- a/permission_handler_android/pubspec.yaml +++ b/permission_handler_android/pubspec.yaml @@ -1,7 +1,7 @@ name: permission_handler_android description: Permission plugin for Flutter. This plugin provides the Android API to request and check permissions. homepage: https://github.com/baseflow/flutter-permission-handler -version: 13.0.2 +version: 13.0.3 environment: sdk: ^3.5.0 From 98ae892921e250d00c3341f45bc8908f8fe93b01 Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 27 May 2026 14:53:25 +0200 Subject: [PATCH 12/57] Updated android pakcage version to 14 (breaking) --- permission_handler/pubspec.yaml | 8 ++++---- permission_handler_android/CHANGELOG.md | 10 ++++++---- permission_handler_android/pubspec.yaml | 2 +- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/permission_handler/pubspec.yaml b/permission_handler/pubspec.yaml index 60ee8f94e..853bb8fdd 100644 --- a/permission_handler/pubspec.yaml +++ b/permission_handler/pubspec.yaml @@ -24,11 +24,11 @@ dependencies: flutter: sdk: flutter meta: ^1.7.0 - permission_handler_android: ^13.0.0 - permission_handler_apple: ^9.4.6 + permission_handler_android: ^14.0.0 + permission_handler_apple: ^9.4.8 permission_handler_html: ^0.1.1 - permission_handler_windows: ^0.2.1 - permission_handler_platform_interface: ^4.3.0 + permission_handler_windows: ^0.2.2 + permission_handler_platform_interface: ^4.3.1 dev_dependencies: flutter_lints: ^5.0.0 diff --git a/permission_handler_android/CHANGELOG.md b/permission_handler_android/CHANGELOG.md index deca632fc..b895ea7ed 100644 --- a/permission_handler_android/CHANGELOG.md +++ b/permission_handler_android/CHANGELOG.md @@ -1,14 +1,16 @@ -## 13.0.3 +## 14.0.0 -* Bump compileSDK version to 37 +- **BREAKING CHANGES:** When updating to version 14.0.0 make sure to also set the `compileSdkVersion` in the `app/build.gradle` file to `37`. +- Updates Android `compileSdkVersion: 35` to `37` +- Bump compileSDK version to 37 ## 13.0.2 -* Added support for the new Android 17 permission `ACCESS_LOCAL_NETWORK` +- Added support for the new Android 17 permission `ACCESS_LOCAL_NETWORK` ## 13.0.1 -* fix: Resolve `PermissionRequestInProgressException` when app is relaunched with non-standard launchMode. +- fix: Resolve `PermissionRequestInProgressException` when app is relaunched with non-standard launchMode. ## 13.0.0 diff --git a/permission_handler_android/pubspec.yaml b/permission_handler_android/pubspec.yaml index fb1bb8aec..045c2247f 100644 --- a/permission_handler_android/pubspec.yaml +++ b/permission_handler_android/pubspec.yaml @@ -1,7 +1,7 @@ name: permission_handler_android description: Permission plugin for Flutter. This plugin provides the Android API to request and check permissions. homepage: https://github.com/baseflow/flutter-permission-handler -version: 13.0.3 +version: 14.0.0 environment: sdk: ^3.5.0 From 7aa86a30791d751bd0636cfcd72a7c1853faa242 Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 27 May 2026 15:00:27 +0200 Subject: [PATCH 13/57] Just a typo --- .../java/com/baseflow/permissionhandler/PermissionUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionUtils.java b/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionUtils.java index b9a8e0644..7b5849692 100644 --- a/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionUtils.java +++ b/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionUtils.java @@ -95,7 +95,7 @@ static int parseManifestName(String permission) { return PermissionConstants.PERMISSION_GROUP_AUDIO; case Manifest.permission.SCHEDULE_EXACT_ALARM: return PermissionConstants.PERMISSION_GROUP_SCHEDULE_EXACT_ALARM; - case Manifest.permission.ACESS_LOCAL_NETWORK: + case Manifest.permission.ACCESS_LOCAL_NETWORK: return PermissionConstants.PERMISSION_GROUP_ACCESS_LOCAL_NETWORK; default: return PermissionConstants.PERMISSION_GROUP_UNKNOWN; From 3b21c917fe21b4f3dd06200a7f6060867cbab685 Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 3 Jun 2026 10:42:03 +0200 Subject: [PATCH 14/57] missing defs --- permission_handler/CHANGELOG.md | 6 +++++- permission_handler/pubspec.yaml | 4 ++-- permission_handler_platform_interface/CHANGELOG.md | 4 ++++ .../lib/src/permissions.dart | 2 ++ permission_handler_platform_interface/pubspec.yaml | 2 +- 5 files changed, 14 insertions(+), 4 deletions(-) diff --git a/permission_handler/CHANGELOG.md b/permission_handler/CHANGELOG.md index 4d08ef4ef..4303f3752 100644 --- a/permission_handler/CHANGELOG.md +++ b/permission_handler/CHANGELOG.md @@ -1,3 +1,8 @@ +## 13.0.0 + +- **BREAKING CHANGE:** , android compilesdk now set to version `compileSdkVersion 37` +- Added support for the new Android 17 permission `ACCESS_LOCAL_NETWORK` + ## 12.0.3 - Rewrites the "iOS - CocaoPods" section in the README.md to match version 8.0.0 of the permission_handler. @@ -6,7 +11,6 @@ ## 12.0.2 - Updates the documentation to include instructions on Swift Package Manager (SPM) support. -- Added support for the new Android 17 permission `ACCESS_LOCAL_NETWORK` ## 12.0.1 diff --git a/permission_handler/pubspec.yaml b/permission_handler/pubspec.yaml index 853bb8fdd..716a2674f 100644 --- a/permission_handler/pubspec.yaml +++ b/permission_handler/pubspec.yaml @@ -2,7 +2,7 @@ name: permission_handler description: Permission plugin for Flutter. This plugin provides a cross-platform (iOS, Android) API to request and check permissions. repository: https://github.com/baseflow/flutter-permission-handler issue_tracker: https://github.com/Baseflow/flutter-permission-handler/issues -version: 12.0.3 +version: 13.0.0 environment: sdk: ^3.5.0 @@ -28,7 +28,7 @@ dependencies: permission_handler_apple: ^9.4.8 permission_handler_html: ^0.1.1 permission_handler_windows: ^0.2.2 - permission_handler_platform_interface: ^4.3.1 + permission_handler_platform_interface: ^4.3.2 dev_dependencies: flutter_lints: ^5.0.0 diff --git a/permission_handler_platform_interface/CHANGELOG.md b/permission_handler_platform_interface/CHANGELOG.md index 510ff0a95..a75b9f029 100644 --- a/permission_handler_platform_interface/CHANGELOG.md +++ b/permission_handler_platform_interface/CHANGELOG.md @@ -1,3 +1,7 @@ +## 4.3.2 + +* Fix support for the new Android 17 permission `ACCESS_LOCAL_NETWORK` + ## 4.3.1 * Added support for the new Android 17 permission `ACCESS_LOCAL_NETWORK` diff --git a/permission_handler_platform_interface/lib/src/permissions.dart b/permission_handler_platform_interface/lib/src/permissions.dart index 9310520cd..8eb1f743f 100644 --- a/permission_handler_platform_interface/lib/src/permissions.dart +++ b/permission_handler_platform_interface/lib/src/permissions.dart @@ -374,6 +374,7 @@ class Permission { calendarFullAccess, assistant, backgroundRefresh, + accessLocalNetwork, ]; static const List _names = [ @@ -417,6 +418,7 @@ class Permission { 'calendarFullAccess', 'assistant', 'backgroundRefresh', + 'accessLocalNetwork', ]; @override diff --git a/permission_handler_platform_interface/pubspec.yaml b/permission_handler_platform_interface/pubspec.yaml index 6dce893af..665dac0b0 100644 --- a/permission_handler_platform_interface/pubspec.yaml +++ b/permission_handler_platform_interface/pubspec.yaml @@ -3,7 +3,7 @@ description: A common platform interface for the permission_handler plugin. homepage: https://github.com/baseflow/flutter-permission-handler/tree/master/permission_handler_platform_interface # NOTE: We strongly prefer non-breaking changes, even at the expense of a # less-clean API. See https://flutter.dev/go/platform-interface-breaking-changes -version: 4.3.1 +version: 4.3.2 environment: sdk: ^3.5.0 From 473cbcbc865770999404e775266458c981874180 Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 3 Jun 2026 10:42:47 +0200 Subject: [PATCH 15/57] ... --- permission_handler/CHANGELOG.md | 4 ++++ permission_handler/pubspec.yaml | 4 ++-- permission_handler_android/CHANGELOG.md | 4 ++++ permission_handler_android/pubspec.yaml | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/permission_handler/CHANGELOG.md b/permission_handler/CHANGELOG.md index 4303f3752..df454a31e 100644 --- a/permission_handler/CHANGELOG.md +++ b/permission_handler/CHANGELOG.md @@ -1,3 +1,7 @@ +## 13.0.1 + +- version bump + ## 13.0.0 - **BREAKING CHANGE:** , android compilesdk now set to version `compileSdkVersion 37` diff --git a/permission_handler/pubspec.yaml b/permission_handler/pubspec.yaml index 716a2674f..7f8b93f42 100644 --- a/permission_handler/pubspec.yaml +++ b/permission_handler/pubspec.yaml @@ -2,7 +2,7 @@ name: permission_handler description: Permission plugin for Flutter. This plugin provides a cross-platform (iOS, Android) API to request and check permissions. repository: https://github.com/baseflow/flutter-permission-handler issue_tracker: https://github.com/Baseflow/flutter-permission-handler/issues -version: 13.0.0 +version: 13.0.1 environment: sdk: ^3.5.0 @@ -24,7 +24,7 @@ dependencies: flutter: sdk: flutter meta: ^1.7.0 - permission_handler_android: ^14.0.0 + permission_handler_android: ^14.0.1 permission_handler_apple: ^9.4.8 permission_handler_html: ^0.1.1 permission_handler_windows: ^0.2.2 diff --git a/permission_handler_android/CHANGELOG.md b/permission_handler_android/CHANGELOG.md index b895ea7ed..7180a5985 100644 --- a/permission_handler_android/CHANGELOG.md +++ b/permission_handler_android/CHANGELOG.md @@ -1,3 +1,7 @@ +## 14.0.1 + +- Version bump + ## 14.0.0 - **BREAKING CHANGES:** When updating to version 14.0.0 make sure to also set the `compileSdkVersion` in the `app/build.gradle` file to `37`. diff --git a/permission_handler_android/pubspec.yaml b/permission_handler_android/pubspec.yaml index 045c2247f..efd02930e 100644 --- a/permission_handler_android/pubspec.yaml +++ b/permission_handler_android/pubspec.yaml @@ -1,7 +1,7 @@ name: permission_handler_android description: Permission plugin for Flutter. This plugin provides the Android API to request and check permissions. homepage: https://github.com/baseflow/flutter-permission-handler -version: 14.0.0 +version: 14.0.1 environment: sdk: ^3.5.0 From 586f42146789425e5cc95c39644ff0893ac09dc3 Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 27 May 2026 15:19:03 +0200 Subject: [PATCH 16/57] ... --- .../permissionhandler/PermissionUtils.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionUtils.java b/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionUtils.java index 7b5849692..35cc35e2d 100644 --- a/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionUtils.java +++ b/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionUtils.java @@ -605,9 +605,21 @@ static List getManifestNames( ) ) permissionNames.add(Manifest.permission.SCHEDULE_EXACT_ALARM); break; + case PermissionConstants.PERMISSION_GROUP_ACCESS_LOCAL_NETWORK: + // The ACCESS_LOCAL_NETWORK permission is introduced in API level 37 (Cinnamon Bun) + // API 36 was allowed but only with e.g. NEARBY_WIFI_DEVICES, so we should not handle permissions on pre Android 37 devices. + // Prior to 36, this was always allowed. + if ( + Build.VERSION.SDK_INT >= Build.VERSION_CODES.CINNAMON_BUN && + hasPermissionInManifest( + context, + permissionNames, + Manifest.permission.ACCESS_LOCAL_NETWORK + ) + ) permissionNames.add(Manifest.permission.ACCESS_LOCAL_NETWORK); + break; case PermissionConstants.PERMISSION_GROUP_MEDIA_LIBRARY: case PermissionConstants.PERMISSION_GROUP_REMINDERS: - case PermissionConstants.PERMISSION_GROUP_ACCESS_LOCAL_NETWORK: case PermissionConstants.PERMISSION_GROUP_UNKNOWN: return null; } From b28b5a1f793be651eee1cdf665d163f7cd483185 Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 3 Jun 2026 10:46:26 +0200 Subject: [PATCH 17/57] dart formatting --- permission_handler/example/lib/main.dart | 92 +++--- .../test/permission_handler_test.dart | 93 +++--- .../example/lib/main.dart | 52 ++-- .../example/lib/main.dart | 70 +++-- permission_handler_html/example/lib/main.dart | 97 +++--- .../lib/permission_handler_html.dart | 17 +- permission_handler_html/lib/web_delegate.dart | 30 +- .../method_channel_permission_handler.dart | 29 +- .../lib/src/method_channel/utils/codec.dart | 11 +- ...permission_handler_platform_interface.dart | 9 +- .../method_channel/method_channel_mock.dart | 6 +- ...ethod_channel_permission_handler_test.dart | 284 +++++++++--------- .../src/method_channel/utils/coded_test.dart | 7 +- ...ssion_handler_platform_interface_test.dart | 113 +++---- .../test/src/permission_status_test.dart | 55 ++-- .../test/src/permissions_test.dart | 70 ++--- .../test/src/service_status_test.dart | 18 +- .../example/lib/main.dart | 66 ++-- 18 files changed, 604 insertions(+), 515 deletions(-) diff --git a/permission_handler/example/lib/main.dart b/permission_handler/example/lib/main.dart index e37e51302..7a6ab62bc 100644 --- a/permission_handler/example/lib/main.dart +++ b/permission_handler/example/lib/main.dart @@ -43,41 +43,40 @@ class _PermissionHandlerWidgetState extends State { Widget build(BuildContext context) { return Center( child: ListView( - children: - Permission.values - .where((permission) { - if (Platform.isIOS) { - return permission != Permission.unknown && - permission != Permission.phone && - permission != Permission.sms && - permission != Permission.ignoreBatteryOptimizations && - permission != Permission.accessMediaLocation && - permission != Permission.activityRecognition && - permission != Permission.manageExternalStorage && - permission != Permission.systemAlertWindow && - permission != Permission.requestInstallPackages && - permission != Permission.accessNotificationPolicy && - permission != Permission.bluetoothScan && - permission != Permission.bluetoothAdvertise && - permission != Permission.bluetoothConnect && - permission != Permission.nearbyWifiDevices && - permission != Permission.videos && - permission != Permission.audio && - permission != Permission.scheduleExactAlarm && - permission != Permission.sensorsAlways; - } else { - return permission != Permission.unknown && - permission != Permission.mediaLibrary && - permission != Permission.photosAddOnly && - permission != Permission.reminders && - permission != Permission.bluetooth && - permission != Permission.appTrackingTransparency && - permission != Permission.criticalAlerts && - permission != Permission.assistant; - } - }) - .map((permission) => PermissionWidget(permission)) - .toList(), + children: Permission.values + .where((permission) { + if (Platform.isIOS) { + return permission != Permission.unknown && + permission != Permission.phone && + permission != Permission.sms && + permission != Permission.ignoreBatteryOptimizations && + permission != Permission.accessMediaLocation && + permission != Permission.activityRecognition && + permission != Permission.manageExternalStorage && + permission != Permission.systemAlertWindow && + permission != Permission.requestInstallPackages && + permission != Permission.accessNotificationPolicy && + permission != Permission.bluetoothScan && + permission != Permission.bluetoothAdvertise && + permission != Permission.bluetoothConnect && + permission != Permission.nearbyWifiDevices && + permission != Permission.videos && + permission != Permission.audio && + permission != Permission.scheduleExactAlarm && + permission != Permission.sensorsAlways; + } else { + return permission != Permission.unknown && + permission != Permission.mediaLibrary && + permission != Permission.photosAddOnly && + permission != Permission.reminders && + permission != Permission.bluetooth && + permission != Permission.appTrackingTransparency && + permission != Permission.criticalAlerts && + permission != Permission.assistant; + } + }) + .map((permission) => PermissionWidget(permission)) + .toList(), ), ); } @@ -136,18 +135,17 @@ class _PermissionState extends State { _permissionStatus.toString(), style: TextStyle(color: getPermissionColor()), ), - trailing: - (widget.permission is PermissionWithService) - ? IconButton( - icon: const Icon(Icons.info, color: Colors.white), - onPressed: () { - checkServiceStatus( - context, - widget.permission as PermissionWithService, - ); - }, - ) - : null, + trailing: (widget.permission is PermissionWithService) + ? IconButton( + icon: const Icon(Icons.info, color: Colors.white), + onPressed: () { + checkServiceStatus( + context, + widget.permission as PermissionWithService, + ); + }, + ) + : null, onTap: () { requestPermission(widget.permission); }, diff --git a/permission_handler/test/permission_handler_test.dart b/permission_handler/test/permission_handler_test.dart index ae666e9a2..4b51c142c 100644 --- a/permission_handler/test/permission_handler_test.dart +++ b/permission_handler/test/permission_handler_test.dart @@ -23,21 +23,27 @@ void main() { }); test( - // ignore: lines_longer_than_80_chars - 'PermissionActions on Permission: get shouldShowRequestRationale should return true when on android', - () async { - final mockPermissionHandlerPlatform = PermissionHandlerPlatform.instance; - - when(mockPermissionHandlerPlatform - .shouldShowRequestPermissionRationale(Permission.contacts)) - .thenAnswer((_) => Future.value(true)); - - await Permission.contacts.shouldShowRequestRationale; - - verify(mockPermissionHandlerPlatform - .shouldShowRequestPermissionRationale(Permission.contacts)) - .called(1); - }); + // ignore: lines_longer_than_80_chars + 'PermissionActions on Permission: get shouldShowRequestRationale should return true when on android', + () async { + final mockPermissionHandlerPlatform = + PermissionHandlerPlatform.instance; + + when( + mockPermissionHandlerPlatform.shouldShowRequestPermissionRationale( + Permission.contacts, + ), + ).thenAnswer((_) => Future.value(true)); + + await Permission.contacts.shouldShowRequestRationale; + + verify( + mockPermissionHandlerPlatform.shouldShowRequestPermissionRationale( + Permission.contacts, + ), + ).called(1); + }, + ); test('PermissionActions on Permission: request()', () async { final permissionRequest = Permission.contacts.request(); @@ -65,11 +71,14 @@ void main() { expect(isLimited, false); }); - test('PermissionCheckShortcuts on Permission: get isPermanentlyDenied', - () async { - final isPermanentlyDenied = await Permission.contacts.isPermanentlyDenied; - expect(isPermanentlyDenied, false); - }); + test( + 'PermissionCheckShortcuts on Permission: get isPermanentlyDenied', + () async { + final isPermanentlyDenied = + await Permission.contacts.isPermanentlyDenied; + expect(isPermanentlyDenied, false); + }, + ); test('PermissionCheckShortcuts on Permission: get isProvisional', () async { final isProvisional = await Permission.contacts.isProvisional; @@ -77,23 +86,25 @@ void main() { }); test( - // ignore: lines_longer_than_80_chars - 'ServicePermissionActions on PermissionWithService: get ServiceStatus returns the right service status', - () async { - var serviceStatus = await Permission.phone.serviceStatus; + // ignore: lines_longer_than_80_chars + 'ServicePermissionActions on PermissionWithService: get ServiceStatus returns the right service status', + () async { + var serviceStatus = await Permission.phone.serviceStatus; - expect(serviceStatus, ServiceStatus.enabled); - }); + expect(serviceStatus, ServiceStatus.enabled); + }, + ); test( - // ignore: lines_longer_than_80_chars - 'PermissionListActions on List: request() on a list returns a Map', - () async { - var permissionList = []; - final permissionMap = await permissionList.request(); - - expect(permissionMap, isA>()); - }); + // ignore: lines_longer_than_80_chars + 'PermissionListActions on List: request() on a list returns a Map', + () async { + var permissionList = []; + final permissionMap = await permissionList.request(); + + expect(permissionMap, isA>()); + }, + ); test('onDeniedCallback sets onDenied', () async { bool callbackCalled = false; @@ -151,7 +162,8 @@ void main() { .onDeniedCallback(() => callbackCalled.add('Denied')) .onGrantedCallback(() => callbackCalled.add('Granted')) .onPermanentlyDeniedCallback( - () => callbackCalled.add('PermanentlyDenied')) + () => callbackCalled.add('PermanentlyDenied'), + ) .onRestrictedCallback(() => callbackCalled.add('Restricted')) .onLimitedCallback(() => callbackCalled.add('Limited')) .onProvisionalCallback(() => callbackCalled.add('Provisional')) @@ -166,8 +178,7 @@ class MockPermissionHandlerPlatform extends Mock with // ignore: prefer_mixin MockPlatformInterfaceMixin - implements - PermissionHandlerPlatform { + implements PermissionHandlerPlatform { @override Future checkPermissionStatus(Permission permission) => Future.value(PermissionStatus.granted); @@ -181,7 +192,8 @@ class MockPermissionHandlerPlatform extends Mock @override Future> requestPermissions( - List permissions) { + List permissions, + ) { var permissionsMap = {}; return Future.value(permissionsMap); } @@ -189,10 +201,7 @@ class MockPermissionHandlerPlatform extends Mock @override Future shouldShowRequestPermissionRationale(Permission? permission) { return super.noSuchMethod( - Invocation.method( - #shouldShowPermissionRationale, - [permission], - ), + Invocation.method(#shouldShowPermissionRationale, [permission]), returnValue: Future.value(true), ); } diff --git a/permission_handler_android/example/lib/main.dart b/permission_handler_android/example/lib/main.dart index 4a0a6e052..f8f49b03d 100644 --- a/permission_handler_android/example/lib/main.dart +++ b/permission_handler_android/example/lib/main.dart @@ -42,21 +42,20 @@ class _PermissionHandlerWidgetState extends State { Widget build(BuildContext context) { return Center( child: ListView( - children: - Permission.values - .where((permission) { - return permission != Permission.unknown && - permission != Permission.mediaLibrary && - permission != Permission.photosAddOnly && - permission != Permission.reminders && - permission != Permission.bluetooth && - permission != Permission.appTrackingTransparency && - permission != Permission.criticalAlerts && - permission != Permission.assistant && - permission != Permission.backgroundRefresh; - }) - .map((permission) => PermissionWidget(permission)) - .toList(), + children: Permission.values + .where((permission) { + return permission != Permission.unknown && + permission != Permission.mediaLibrary && + permission != Permission.photosAddOnly && + permission != Permission.reminders && + permission != Permission.bluetooth && + permission != Permission.appTrackingTransparency && + permission != Permission.criticalAlerts && + permission != Permission.assistant && + permission != Permission.backgroundRefresh; + }) + .map((permission) => PermissionWidget(permission)) + .toList(), ), ); } @@ -118,18 +117,17 @@ class _PermissionState extends State { _permissionStatus.toString(), style: TextStyle(color: getPermissionColor()), ), - trailing: - (widget._permission is PermissionWithService) - ? IconButton( - icon: const Icon(Icons.info, color: Colors.white), - onPressed: () { - checkServiceStatus( - context, - widget._permission as PermissionWithService, - ); - }, - ) - : null, + trailing: (widget._permission is PermissionWithService) + ? IconButton( + icon: const Icon(Icons.info, color: Colors.white), + onPressed: () { + checkServiceStatus( + context, + widget._permission as PermissionWithService, + ); + }, + ) + : null, onTap: () { requestPermission(widget._permission); }, diff --git a/permission_handler_apple/example/lib/main.dart b/permission_handler_apple/example/lib/main.dart index 4750f1ac5..7605e3c48 100644 --- a/permission_handler_apple/example/lib/main.dart +++ b/permission_handler_apple/example/lib/main.dart @@ -41,30 +41,29 @@ class _PermissionHandlerWidgetState extends State { Widget build(BuildContext context) { return Center( child: ListView( - children: - Permission.values - .where((permission) { - return permission != Permission.unknown && - permission != Permission.phone && - permission != Permission.sms && - permission != Permission.ignoreBatteryOptimizations && - permission != Permission.accessMediaLocation && - permission != Permission.activityRecognition && - permission != Permission.manageExternalStorage && - permission != Permission.systemAlertWindow && - permission != Permission.requestInstallPackages && - permission != Permission.accessNotificationPolicy && - permission != Permission.bluetoothScan && - permission != Permission.bluetoothAdvertise && - permission != Permission.bluetoothConnect && - permission != Permission.nearbyWifiDevices && - permission != Permission.videos && - permission != Permission.audio && - permission != Permission.scheduleExactAlarm && - permission != Permission.sensorsAlways; - }) - .map((permission) => PermissionWidget(permission)) - .toList(), + children: Permission.values + .where((permission) { + return permission != Permission.unknown && + permission != Permission.phone && + permission != Permission.sms && + permission != Permission.ignoreBatteryOptimizations && + permission != Permission.accessMediaLocation && + permission != Permission.activityRecognition && + permission != Permission.manageExternalStorage && + permission != Permission.systemAlertWindow && + permission != Permission.requestInstallPackages && + permission != Permission.accessNotificationPolicy && + permission != Permission.bluetoothScan && + permission != Permission.bluetoothAdvertise && + permission != Permission.bluetoothConnect && + permission != Permission.nearbyWifiDevices && + permission != Permission.videos && + permission != Permission.audio && + permission != Permission.scheduleExactAlarm && + permission != Permission.sensorsAlways; + }) + .map((permission) => PermissionWidget(permission)) + .toList(), ), ); } @@ -125,18 +124,17 @@ class _PermissionState extends State { _permissionStatus.toString(), style: TextStyle(color: getPermissionColor()), ), - trailing: - (widget.permission is PermissionWithService) - ? IconButton( - icon: const Icon(Icons.info, color: Colors.white), - onPressed: () { - checkServiceStatus( - context, - widget.permission as PermissionWithService, - ); - }, - ) - : null, + trailing: (widget.permission is PermissionWithService) + ? IconButton( + icon: const Icon(Icons.info, color: Colors.white), + onPressed: () { + checkServiceStatus( + context, + widget.permission as PermissionWithService, + ); + }, + ) + : null, onTap: () { requestPermission(widget.permission); }, diff --git a/permission_handler_html/example/lib/main.dart b/permission_handler_html/example/lib/main.dart index e3650eba8..37ffcf5b3 100644 --- a/permission_handler_html/example/lib/main.dart +++ b/permission_handler_html/example/lib/main.dart @@ -3,29 +3,33 @@ import 'package:flutter/material.dart'; import 'package:permission_handler_platform_interface/permission_handler_platform_interface.dart'; void main() { - runApp(BaseflowPluginExample( + runApp( + BaseflowPluginExample( pluginName: 'Permission Handler', githubURL: 'https://github.com/Baseflow/flutter-permission-handler', pubDevURL: 'https://pub.dev/packages/permission_handler', - pages: [PermissionHandlerWidget.createPage()])); + pages: [PermissionHandlerWidget.createPage()], + ), + ); } ///Defines the main theme color final MaterialColor themeMaterialColor = BaseflowPluginExample.createMaterialColor( - const Color.fromRGBO(48, 49, 60, 1)); + const Color.fromRGBO(48, 49, 60, 1), + ); /// A Flutter application demonstrating the functionality of this plugin class PermissionHandlerWidget extends StatefulWidget { /// Creates a [PermissionHandlerWidget]. - const PermissionHandlerWidget({ - super.key, - }); + const PermissionHandlerWidget({super.key}); /// Create a page containing the functionality of this plugin static ExamplePage createPage() { return ExamplePage( - Icons.location_on, (context) => const PermissionHandlerWidget()); + Icons.location_on, + (context) => const PermissionHandlerWidget(), + ); } @override @@ -38,18 +42,19 @@ class _PermissionHandlerWidgetState extends State { Widget build(BuildContext context) { return Center( child: ListView( - children: Permission.values - .where((permission) { - return permission != Permission.unknown && - permission != Permission.mediaLibrary && - permission != Permission.photos && - permission != Permission.photosAddOnly && - permission != Permission.reminders && - permission != Permission.appTrackingTransparency && - permission != Permission.criticalAlerts; - }) - .map((permission) => PermissionWidget(permission)) - .toList()), + children: Permission.values + .where((permission) { + return permission != Permission.unknown && + permission != Permission.mediaLibrary && + permission != Permission.photos && + permission != Permission.photosAddOnly && + permission != Permission.reminders && + permission != Permission.appTrackingTransparency && + permission != Permission.criticalAlerts; + }) + .map((permission) => PermissionWidget(permission)) + .toList(), + ), ); } } @@ -57,10 +62,7 @@ class _PermissionHandlerWidgetState extends State { /// Permission widget containing information about the passed [Permission] class PermissionWidget extends StatefulWidget { /// Constructs a [PermissionWidget] for the supplied [Permission] - const PermissionWidget( - this._permission, { - super.key, - }); + const PermissionWidget(this._permission, {super.key}); final Permission _permission; @@ -83,9 +85,12 @@ class _PermissionState extends State { } void _listenForPermissionStatus() async { - await _permissionHandler.checkPermissionStatus(widget._permission).then( - (status) => setState(() => _permissionStatus = status), - onError: (error, st) => debugPrint('$error')); + await _permissionHandler + .checkPermissionStatus(widget._permission) + .then( + (status) => setState(() => _permissionStatus = status), + onError: (error, st) => debugPrint('$error'), + ); } Color getPermissionColor() { @@ -114,14 +119,14 @@ class _PermissionState extends State { ), trailing: (widget._permission is PermissionWithService) ? IconButton( - icon: const Icon( - Icons.info, - color: Colors.white, - ), + icon: const Icon(Icons.info, color: Colors.white), onPressed: () { checkServiceStatus( - context, widget._permission as PermissionWithService); - }) + context, + widget._permission as PermissionWithService, + ); + }, + ) : null, onTap: () { requestPermission(widget._permission); @@ -130,18 +135,26 @@ class _PermissionState extends State { } void checkServiceStatus( - BuildContext context, PermissionWithService permission) async { - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text( - (await _permissionHandler.checkServiceStatus(permission)).toString()), - )); + BuildContext context, + PermissionWithService permission, + ) async { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + (await _permissionHandler.checkServiceStatus(permission)).toString(), + ), + ), + ); } Future requestPermission(Permission permission) async { - await _permissionHandler.requestPermissions([permission]).then( - (status) => setState(() { - _permissionStatus = status[permission] ?? PermissionStatus.denied; - }), - onError: (error, st) => debugPrint('$error')); + await _permissionHandler + .requestPermissions([permission]) + .then( + (status) => setState(() { + _permissionStatus = status[permission] ?? PermissionStatus.denied; + }), + onError: (error, st) => debugPrint('$error'), + ); } } diff --git a/permission_handler_html/lib/permission_handler_html.dart b/permission_handler_html/lib/permission_handler_html.dart index 8be2fa7c4..db6b28d37 100644 --- a/permission_handler_html/lib/permission_handler_html.dart +++ b/permission_handler_html/lib/permission_handler_html.dart @@ -33,22 +33,18 @@ class WebPermissionHandler extends PermissionHandlerPlatform { /// Registers the web plugin implementation. static void registerWith(Registrar registrar) { PermissionHandlerPlatform.instance = WebPermissionHandler( - webDelegate: WebDelegate( - _devices, - _geolocation, - _htmlPermissions, - ), + webDelegate: WebDelegate(_devices, _geolocation, _htmlPermissions), ); } /// Constructs a WebPermissionHandler. - WebPermissionHandler({ - required WebDelegate webDelegate, - }) : _webDelegate = webDelegate; + WebPermissionHandler({required WebDelegate webDelegate}) + : _webDelegate = webDelegate; @override Future> requestPermissions( - List permissions) async { + List permissions, + ) async { return _webDelegate.requestPermissions(permissions); } @@ -64,7 +60,8 @@ class WebPermissionHandler extends PermissionHandlerPlatform { @override Future shouldShowRequestPermissionRationale( - Permission permission) async { + Permission permission, + ) async { return SynchronousFuture(false); } diff --git a/permission_handler_html/lib/web_delegate.dart b/permission_handler_html/lib/web_delegate.dart index 1db991418..e9a381ece 100644 --- a/permission_handler_html/lib/web_delegate.dart +++ b/permission_handler_html/lib/web_delegate.dart @@ -13,9 +13,9 @@ class WebDelegate { web.MediaDevices? devices, web.Geolocation? geolocation, web.Permissions? permissions, - ) : _devices = devices, - _geolocation = geolocation, - _htmlPermissions = permissions; + ) : _devices = devices, + _geolocation = geolocation, + _htmlPermissions = permissions; /// The html media devices object used to request camera and microphone permissions. final web.MediaDevices? _devices; @@ -61,7 +61,9 @@ class WebDelegate { } Future _permissionStatusState( - String webPermissionName, web.Permissions? permissions) async { + String webPermissionName, + web.Permissions? permissions, + ) async { final webPermissionStatus = await permissions ?.query(_PermissionDescriptor(name: webPermissionName)) .toDart; @@ -129,9 +131,9 @@ class WebDelegate { } Future _requestNotificationPermission() async { - return web.Notification.requestPermission() - .toDart - .then((permission) => (permission == "granted".toJS)); + return web.Notification.requestPermission().toDart.then( + (permission) => (permission == "granted".toJS), + ); } Future _requestLocationPermission() async { @@ -152,14 +154,16 @@ class WebDelegate { } Future _requestSingularPermission( - Permission permission) async { + Permission permission, + ) async { bool permissionGranted = switch (permission) { Permission.microphone => await _requestMicrophonePermission(), Permission.camera => await _requestCameraPermission(), Permission.notification => await _requestNotificationPermission(), Permission.location => await _requestLocationPermission(), _ => throw UnsupportedError( - 'The ${permission.toString()} permission is currently not supported on web.') + 'The ${permission.toString()} permission is currently not supported on web.', + ), }; if (!permissionGranted) { @@ -173,13 +177,15 @@ class WebDelegate { /// /// Returns a [Map] containing the status per requested [Permission]. Future> requestPermissions( - List permissions) async { + List permissions, + ) async { final Map permissionStatusMap = {}; for (final permission in permissions) { try { - permissionStatusMap[permission] = - await _requestSingularPermission(permission); + permissionStatusMap[permission] = await _requestSingularPermission( + permission, + ); } on UnimplementedError { rethrow; } diff --git a/permission_handler_platform_interface/lib/src/method_channel/method_channel_permission_handler.dart b/permission_handler_platform_interface/lib/src/method_channel/method_channel_permission_handler.dart index 5f03e3e7a..ca11e55d0 100644 --- a/permission_handler_platform_interface/lib/src/method_channel/method_channel_permission_handler.dart +++ b/permission_handler_platform_interface/lib/src/method_channel/method_channel_permission_handler.dart @@ -6,8 +6,9 @@ import 'package:flutter/services.dart'; import '../../permission_handler_platform_interface.dart'; import 'utils/codec.dart'; -const MethodChannel _methodChannel = - MethodChannel('flutter.baseflow.com/permissions/methods'); +const MethodChannel _methodChannel = MethodChannel( + 'flutter.baseflow.com/permissions/methods', +); /// An implementation of [PermissionHandlerPlatform] that uses [MethodChannel]s. class MethodChannelPermissionHandler extends PermissionHandlerPlatform { @@ -15,7 +16,9 @@ class MethodChannelPermissionHandler extends PermissionHandlerPlatform { @override Future checkPermissionStatus(Permission permission) async { final status = await _methodChannel.invokeMethod( - 'checkPermissionStatus', permission.value); + 'checkPermissionStatus', + permission.value, + ); return decodePermissionStatus(status); } @@ -52,7 +55,9 @@ class MethodChannelPermissionHandler extends PermissionHandlerPlatform { @override Future checkServiceStatus(Permission permission) async { final status = await _methodChannel.invokeMethod( - 'checkServiceStatus', permission.value); + 'checkServiceStatus', + permission.value, + ); return decodeServiceStatus(status); } @@ -74,10 +79,13 @@ class MethodChannelPermissionHandler extends PermissionHandlerPlatform { /// Returns a [Map] containing the status per requested [Permission]. @override Future> requestPermissions( - List permissions) async { + List permissions, + ) async { final data = encodePermissions(permissions); - final status = - await _methodChannel.invokeMethod('requestPermissions', data); + final status = await _methodChannel.invokeMethod( + 'requestPermissions', + data, + ); return decodePermissionRequestResult(Map.from(status)); } @@ -88,13 +96,16 @@ class MethodChannelPermissionHandler extends PermissionHandlerPlatform { /// returns [false]. @override Future shouldShowRequestPermissionRationale( - Permission permission) async { + Permission permission, + ) async { if (defaultTargetPlatform != TargetPlatform.android) { return false; } final shouldShowRationale = await _methodChannel.invokeMethod( - 'shouldShowRequestPermissionRationale', permission.value); + 'shouldShowRequestPermissionRationale', + permission.value, + ); return shouldShowRationale ?? false; } diff --git a/permission_handler_platform_interface/lib/src/method_channel/utils/codec.dart b/permission_handler_platform_interface/lib/src/method_channel/utils/codec.dart index dc5db075c..99bd0768a 100644 --- a/permission_handler_platform_interface/lib/src/method_channel/utils/codec.dart +++ b/permission_handler_platform_interface/lib/src/method_channel/utils/codec.dart @@ -13,9 +13,14 @@ ServiceStatus decodeServiceStatus(int value) { /// Converts the given [Map] of [int]s into a [Map] with [Permission]s as /// keys and their respective [PermissionStatus] as value. Map decodePermissionRequestResult( - Map value) { - return value.map((key, value) => MapEntry( - Permission.byValue(key), PermissionStatusValue.statusByValue(value))); + Map value, +) { + return value.map( + (key, value) => MapEntry( + Permission.byValue(key), + PermissionStatusValue.statusByValue(value), + ), + ); } /// Converts the given [List] of [Permission]s into a [List] of [int]s which diff --git a/permission_handler_platform_interface/lib/src/permission_handler_platform_interface.dart b/permission_handler_platform_interface/lib/src/permission_handler_platform_interface.dart index 32cb2b722..24685265e 100644 --- a/permission_handler_platform_interface/lib/src/permission_handler_platform_interface.dart +++ b/permission_handler_platform_interface/lib/src/permission_handler_platform_interface.dart @@ -32,7 +32,8 @@ abstract class PermissionHandlerPlatform extends PlatformInterface { /// Checks the current status of the given [Permission]. Future checkPermissionStatus(Permission permission) { throw UnimplementedError( - 'checkPermissionStatus() has not been implemented.'); + 'checkPermissionStatus() has not been implemented.', + ); } /// Checks the current status of the service associated with the given @@ -73,7 +74,8 @@ abstract class PermissionHandlerPlatform extends PlatformInterface { /// /// Returns a [Map] containing the status per requested [Permission]. Future> requestPermissions( - List permissions) { + List permissions, + ) { throw UnimplementedError('requestPermissions() has not been implemented.'); } @@ -83,6 +85,7 @@ abstract class PermissionHandlerPlatform extends PlatformInterface { /// returns [false]. Future shouldShowRequestPermissionRationale(Permission permission) { throw UnimplementedError( - 'shouldShowRequestPermissionRationale() has not been implemented.'); + 'shouldShowRequestPermissionRationale() has not been implemented.', + ); } } diff --git a/permission_handler_platform_interface/test/src/method_channel/method_channel_mock.dart b/permission_handler_platform_interface/test/src/method_channel/method_channel_mock.dart index 2b5da964a..77e4671f4 100644 --- a/permission_handler_platform_interface/test/src/method_channel/method_channel_mock.dart +++ b/permission_handler_platform_interface/test/src/method_channel/method_channel_mock.dart @@ -19,8 +19,10 @@ class MethodChannelMock { Future _handler(MethodCall methodCall) async { if (methodCall.method != method) { - throw MissingPluginException('No implementation found for method ' - '$method on channel ${methodChannel.name}'); + throw MissingPluginException( + 'No implementation found for method ' + '$method on channel ${methodChannel.name}', + ); } return Future.delayed(delay, () { diff --git a/permission_handler_platform_interface/test/src/method_channel/method_channel_permission_handler_test.dart b/permission_handler_platform_interface/test/src/method_channel/method_channel_permission_handler_test.dart index c03c279a1..67def69d1 100644 --- a/permission_handler_platform_interface/test/src/method_channel/method_channel_permission_handler_test.dart +++ b/permission_handler_platform_interface/test/src/method_channel/method_channel_permission_handler_test.dart @@ -4,10 +4,10 @@ import 'package:permission_handler_platform_interface/src/method_channel/method_ import 'method_channel_mock.dart'; List get mockPermissions => List.of({ - Permission.contacts, - Permission.camera, - Permission.calendarWriteOnly, - }); + Permission.contacts, + Permission.camera, + Permission.calendarWriteOnly, +}); Map get mockPermissionMap => {}; @@ -15,129 +15,140 @@ void main() { TestWidgetsFlutterBinding.ensureInitialized(); group('checkPermissionStatus: When checking for permission', () { - test('Should receive granted if user wants access to the requested feature', - () async { - MethodChannelMock( - channelName: 'flutter.baseflow.com/permissions/methods', - method: 'checkPermissionStatus', - result: PermissionStatus.denied.value, - ); - - final permissionStatus = await MethodChannelPermissionHandler() - .checkPermissionStatus(Permission.contacts); - - expect(permissionStatus, PermissionStatus.denied); - }); - - test('Should receive denied if user denied access to the requested feature', - () async { - MethodChannelMock( - channelName: 'flutter.baseflow.com/permissions/methods', - method: 'checkPermissionStatus', - result: PermissionStatus.denied.value, - ); - - final permissionStatus = await MethodChannelPermissionHandler() - .checkPermissionStatus(Permission.contacts); - - expect(permissionStatus, PermissionStatus.denied); - }); - test( - // ignore: lines_longer_than_80_chars - 'Should receive restricted if OS denied rights for to the requested feature', - () async { - MethodChannelMock( - channelName: 'flutter.baseflow.com/permissions/methods', - method: 'checkPermissionStatus', - result: PermissionStatus.restricted.value, - ); + 'Should receive granted if user wants access to the requested feature', + () async { + MethodChannelMock( + channelName: 'flutter.baseflow.com/permissions/methods', + method: 'checkPermissionStatus', + result: PermissionStatus.denied.value, + ); - final permissionStatus = await MethodChannelPermissionHandler() - .checkPermissionStatus(Permission.contacts); + final permissionStatus = await MethodChannelPermissionHandler() + .checkPermissionStatus(Permission.contacts); - expect(permissionStatus, PermissionStatus.restricted); - }); + expect(permissionStatus, PermissionStatus.denied); + }, + ); test( - // ignore: lines_longer_than_80_chars - 'Should receive limited if user has authorized this application for limited access', - () async { - MethodChannelMock( - channelName: 'flutter.baseflow.com/permissions/methods', - method: 'checkPermissionStatus', - result: PermissionStatus.limited.value, - ); + 'Should receive denied if user denied access to the requested feature', + () async { + MethodChannelMock( + channelName: 'flutter.baseflow.com/permissions/methods', + method: 'checkPermissionStatus', + result: PermissionStatus.denied.value, + ); - final permissionStatus = await MethodChannelPermissionHandler() - .checkPermissionStatus(Permission.contacts); + final permissionStatus = await MethodChannelPermissionHandler() + .checkPermissionStatus(Permission.contacts); - expect(permissionStatus, PermissionStatus.limited); - }); + expect(permissionStatus, PermissionStatus.denied); + }, + ); test( - // ignore: lines_longer_than_80_chars - 'Should receive permanentlyDenied if user denied access and selected to never show a request for this permission again', - () async { - MethodChannelMock( - channelName: 'flutter.baseflow.com/permissions/methods', - method: 'checkPermissionStatus', - result: PermissionStatus.permanentlyDenied.value, - ); + // ignore: lines_longer_than_80_chars + 'Should receive restricted if OS denied rights for to the requested feature', + () async { + MethodChannelMock( + channelName: 'flutter.baseflow.com/permissions/methods', + method: 'checkPermissionStatus', + result: PermissionStatus.restricted.value, + ); + + final permissionStatus = await MethodChannelPermissionHandler() + .checkPermissionStatus(Permission.contacts); + + expect(permissionStatus, PermissionStatus.restricted); + }, + ); - final permissionStatus = await MethodChannelPermissionHandler() - .checkPermissionStatus(Permission.contacts); + test( + // ignore: lines_longer_than_80_chars + 'Should receive limited if user has authorized this application for limited access', + () async { + MethodChannelMock( + channelName: 'flutter.baseflow.com/permissions/methods', + method: 'checkPermissionStatus', + result: PermissionStatus.limited.value, + ); + + final permissionStatus = await MethodChannelPermissionHandler() + .checkPermissionStatus(Permission.contacts); + + expect(permissionStatus, PermissionStatus.limited); + }, + ); - expect(permissionStatus, PermissionStatus.permanentlyDenied); - }); + test( + // ignore: lines_longer_than_80_chars + 'Should receive permanentlyDenied if user denied access and selected to never show a request for this permission again', + () async { + MethodChannelMock( + channelName: 'flutter.baseflow.com/permissions/methods', + method: 'checkPermissionStatus', + result: PermissionStatus.permanentlyDenied.value, + ); + + final permissionStatus = await MethodChannelPermissionHandler() + .checkPermissionStatus(Permission.contacts); + + expect(permissionStatus, PermissionStatus.permanentlyDenied); + }, + ); }); group('checkServiceStatus: When checking for service', () { // ignore: lines_longer_than_80_chars test( - 'Should receive disabled if the service for the permission is disabled', - () async { - MethodChannelMock( - channelName: 'flutter.baseflow.com/permissions/methods', - method: 'checkServiceStatus', - result: ServiceStatus.disabled.value, - ); + 'Should receive disabled if the service for the permission is disabled', + () async { + MethodChannelMock( + channelName: 'flutter.baseflow.com/permissions/methods', + method: 'checkServiceStatus', + result: ServiceStatus.disabled.value, + ); - final serviceStatus = await MethodChannelPermissionHandler() - .checkServiceStatus(Permission.contacts); + final serviceStatus = await MethodChannelPermissionHandler() + .checkServiceStatus(Permission.contacts); - expect(serviceStatus, ServiceStatus.disabled); - }); + expect(serviceStatus, ServiceStatus.disabled); + }, + ); - test('Should receive enabled if the service for the permission is enabled', - () async { - MethodChannelMock( - channelName: 'flutter.baseflow.com/permissions/methods', - method: 'checkServiceStatus', - result: ServiceStatus.enabled.value, - ); + test( + 'Should receive enabled if the service for the permission is enabled', + () async { + MethodChannelMock( + channelName: 'flutter.baseflow.com/permissions/methods', + method: 'checkServiceStatus', + result: ServiceStatus.enabled.value, + ); - final serviceStatus = await MethodChannelPermissionHandler() - .checkServiceStatus(Permission.contacts); + final serviceStatus = await MethodChannelPermissionHandler() + .checkServiceStatus(Permission.contacts); - expect(serviceStatus, ServiceStatus.enabled); - }); + expect(serviceStatus, ServiceStatus.enabled); + }, + ); test( - // ignore: lines_longer_than_80_chars - 'Should receive notApplicable if the permission does not have an associated service on the current platform', - () async { - MethodChannelMock( - channelName: 'flutter.baseflow.com/permissions/methods', - method: 'checkServiceStatus', - result: ServiceStatus.notApplicable.value, - ); - - final serviceStatus = await MethodChannelPermissionHandler() - .checkServiceStatus(Permission.contacts); - - expect(serviceStatus, ServiceStatus.notApplicable); - }); + // ignore: lines_longer_than_80_chars + 'Should receive notApplicable if the permission does not have an associated service on the current platform', + () async { + MethodChannelMock( + channelName: 'flutter.baseflow.com/permissions/methods', + method: 'checkServiceStatus', + result: ServiceStatus.notApplicable.value, + ); + + final serviceStatus = await MethodChannelPermissionHandler() + .checkServiceStatus(Permission.contacts); + + expect(serviceStatus, ServiceStatus.notApplicable); + }, + ); }); group('openAppSettings: When opening the App settings', () { @@ -148,8 +159,8 @@ void main() { result: true, ); - final hasOpenedAppSettings = - await MethodChannelPermissionHandler().openAppSettings(); + final hasOpenedAppSettings = await MethodChannelPermissionHandler() + .openAppSettings(); expect(hasOpenedAppSettings, true); }); @@ -161,8 +172,8 @@ void main() { result: false, ); - final hasOpenedAppSettings = - await MethodChannelPermissionHandler().openAppSettings(); + final hasOpenedAppSettings = await MethodChannelPermissionHandler() + .openAppSettings(); expect(hasOpenedAppSettings, false); }); @@ -170,36 +181,39 @@ void main() { group('requestPermissions: When requesting for permission', () { // ignore: lines_longer_than_80_chars - test('returns a Map with all the PermissionStatus of the given permissions', - () async { - MethodChannelMock( - channelName: 'flutter.baseflow.com/permissions/methods', - method: 'requestPermissions', - result: mockPermissionMap, - ); - - final result = await MethodChannelPermissionHandler() - .requestPermissions(mockPermissions); - - expect(result, isA>()); - }); + test( + 'returns a Map with all the PermissionStatus of the given permissions', + () async { + MethodChannelMock( + channelName: 'flutter.baseflow.com/permissions/methods', + method: 'requestPermissions', + result: mockPermissionMap, + ); + + final result = await MethodChannelPermissionHandler() + .requestPermissions(mockPermissions); + + expect(result, isA>()); + }, + ); }); group('shouldShowRequestPermissionRationale:', () { test( - // ignore: lines_longer_than_80_chars - 'should return true when you should show a rationale for requesting permission.', - () async { - MethodChannelMock( - channelName: 'flutter.baseflow.com/permissions/methods', - method: 'shouldShowRequestPermissionRationale', - result: true, - ); - - final shouldShowRationale = await MethodChannelPermissionHandler() - .shouldShowRequestPermissionRationale(mockPermissions.first); - - expect(shouldShowRationale, true); - }); + // ignore: lines_longer_than_80_chars + 'should return true when you should show a rationale for requesting permission.', + () async { + MethodChannelMock( + channelName: 'flutter.baseflow.com/permissions/methods', + method: 'shouldShowRequestPermissionRationale', + result: true, + ); + + final shouldShowRationale = await MethodChannelPermissionHandler() + .shouldShowRequestPermissionRationale(mockPermissions.first); + + expect(shouldShowRationale, true); + }, + ); }); } diff --git a/permission_handler_platform_interface/test/src/method_channel/utils/coded_test.dart b/permission_handler_platform_interface/test/src/method_channel/utils/coded_test.dart index 1742b9fc6..b9037c2b0 100644 --- a/permission_handler_platform_interface/test/src/method_channel/utils/coded_test.dart +++ b/permission_handler_platform_interface/test/src/method_channel/utils/coded_test.dart @@ -12,12 +12,9 @@ void main() { expect(decodeServiceStatus(0), ServiceStatus.disabled); }); - test( - 'decodePermissionRequestResult should convert a map' + test('decodePermissionRequestResult should convert a map' 'to map', () { - var value = { - 1: 1, - }; + var value = {1: 1}; var permissionMap = decodePermissionRequestResult(value); diff --git a/permission_handler_platform_interface/test/src/permission_handler_platform_interface_test.dart b/permission_handler_platform_interface/test/src/permission_handler_platform_interface_test.dart index c965e72ed..3977d648b 100644 --- a/permission_handler_platform_interface/test/src/permission_handler_platform_interface_test.dart +++ b/permission_handler_platform_interface/test/src/permission_handler_platform_interface_test.dart @@ -9,8 +9,10 @@ void main() { group('$PermissionHandlerPlatform', () { test('$MethodChannelPermissionHandler is the default instance', () { - expect(PermissionHandlerPlatform.instance, - isA()); + expect( + PermissionHandlerPlatform.instance, + isA(), + ); }); test('Cannot be implemented with `implements`', () { @@ -30,61 +32,71 @@ void main() { }); test( - // ignore: lines_longer_than_80_chars - 'Default implementation of checkPermissionStatus should throw unimplemented error', - () { - final permissionHandlerPlatform = ExtendsPermissionHandlerPlatform(); - - expect(() { - permissionHandlerPlatform - .checkPermissionStatus(Permission.accessMediaLocation); - }, throwsUnimplementedError); - }); + // ignore: lines_longer_than_80_chars + 'Default implementation of checkPermissionStatus should throw unimplemented error', + () { + final permissionHandlerPlatform = ExtendsPermissionHandlerPlatform(); + + expect(() { + permissionHandlerPlatform.checkPermissionStatus( + Permission.accessMediaLocation, + ); + }, throwsUnimplementedError); + }, + ); test( - // ignore: lines_longer_than_80_chars - 'Default implementation of checkServiceStatus should throw unimplemented error', - () { - final permissionHandlerPlatform = ExtendsPermissionHandlerPlatform(); - - expect(() { - permissionHandlerPlatform - .checkServiceStatus(Permission.accessMediaLocation); - }, throwsUnimplementedError); - }); + // ignore: lines_longer_than_80_chars + 'Default implementation of checkServiceStatus should throw unimplemented error', + () { + final permissionHandlerPlatform = ExtendsPermissionHandlerPlatform(); + + expect(() { + permissionHandlerPlatform.checkServiceStatus( + Permission.accessMediaLocation, + ); + }, throwsUnimplementedError); + }, + ); test( - // ignore: lines_longer_than_80_chars - 'Default implementation of openAppSettings should throw unimplemented error', - () { - final permissionHandlerPlatform = ExtendsPermissionHandlerPlatform(); - - expect( - permissionHandlerPlatform.openAppSettings, throwsUnimplementedError); - }); + // ignore: lines_longer_than_80_chars + 'Default implementation of openAppSettings should throw unimplemented error', + () { + final permissionHandlerPlatform = ExtendsPermissionHandlerPlatform(); + + expect( + permissionHandlerPlatform.openAppSettings, + throwsUnimplementedError, + ); + }, + ); test( - // ignore: lines_longer_than_80_chars - 'Default implementation of requestPermissions should throw unimplemented error', - () { - final permissionHandlerPlatform = ExtendsPermissionHandlerPlatform(); - var permission = [Permission.accessMediaLocation]; - - expect(() { - permissionHandlerPlatform.requestPermissions(permission); - }, throwsUnimplementedError); - }); + // ignore: lines_longer_than_80_chars + 'Default implementation of requestPermissions should throw unimplemented error', + () { + final permissionHandlerPlatform = ExtendsPermissionHandlerPlatform(); + var permission = [Permission.accessMediaLocation]; + + expect(() { + permissionHandlerPlatform.requestPermissions(permission); + }, throwsUnimplementedError); + }, + ); test( - // ignore: lines_longer_than_80_chars - 'Default implementation of shouldShowRequestPermissionRationale should throw unimplemented error', - () { - final permissionHandlerPlatform = ExtendsPermissionHandlerPlatform(); - expect(() { - permissionHandlerPlatform.shouldShowRequestPermissionRationale( - Permission.accessMediaLocation); - }, throwsUnimplementedError); - }); + // ignore: lines_longer_than_80_chars + 'Default implementation of shouldShowRequestPermissionRationale should throw unimplemented error', + () { + final permissionHandlerPlatform = ExtendsPermissionHandlerPlatform(); + expect(() { + permissionHandlerPlatform.shouldShowRequestPermissionRationale( + Permission.accessMediaLocation, + ); + }, throwsUnimplementedError); + }, + ); }); } @@ -99,5 +111,4 @@ class MockPermissionHandlerPlatform extends Mock with // ignore: prefer_mixin MockPlatformInterfaceMixin - implements - PermissionHandlerPlatform {} + implements PermissionHandlerPlatform {} diff --git a/permission_handler_platform_interface/test/src/permission_status_test.dart b/permission_handler_platform_interface/test/src/permission_status_test.dart index d26ee6b32..3e127754d 100644 --- a/permission_handler_platform_interface/test/src/permission_status_test.dart +++ b/permission_handler_platform_interface/test/src/permission_status_test.dart @@ -32,19 +32,32 @@ void main() { }); test( - // ignore: lines_longer_than_80_chars - 'statusByValue should return right index int that corresponds with the right PermissionStatus', - () { - expect(PermissionStatusValue.statusByValue(0), PermissionStatus.denied); - expect(PermissionStatusValue.statusByValue(1), PermissionStatus.granted); - expect( - PermissionStatusValue.statusByValue(2), PermissionStatus.restricted); - expect(PermissionStatusValue.statusByValue(3), PermissionStatus.limited); - expect(PermissionStatusValue.statusByValue(4), - PermissionStatus.permanentlyDenied); - expect( - PermissionStatusValue.statusByValue(5), PermissionStatus.provisional); - }); + // ignore: lines_longer_than_80_chars + 'statusByValue should return right index int that corresponds with the right PermissionStatus', + () { + expect(PermissionStatusValue.statusByValue(0), PermissionStatus.denied); + expect( + PermissionStatusValue.statusByValue(1), + PermissionStatus.granted, + ); + expect( + PermissionStatusValue.statusByValue(2), + PermissionStatus.restricted, + ); + expect( + PermissionStatusValue.statusByValue(3), + PermissionStatus.limited, + ); + expect( + PermissionStatusValue.statusByValue(4), + PermissionStatus.permanentlyDenied, + ); + expect( + PermissionStatusValue.statusByValue(5), + PermissionStatus.provisional, + ); + }, + ); }); group('PermissionStatusGetters', () { @@ -76,11 +89,15 @@ void main() { expect(await mockFuture(PermissionStatus.restricted).isRestricted, true); expect(await mockFuture(PermissionStatus.limited).isLimited, true); expect( - await mockFuture(PermissionStatus.permanentlyDenied) - .isPermanentlyDenied, - true); + await mockFuture( + PermissionStatus.permanentlyDenied, + ).isPermanentlyDenied, + true, + ); expect( - await mockFuture(PermissionStatus.provisional).isProvisional, true); + await mockFuture(PermissionStatus.provisional).isProvisional, + true, + ); }); test('Getters should return false if statement is not met', () async { @@ -89,7 +106,9 @@ void main() { expect(await mockFuture(PermissionStatus.restricted).isDenied, false); expect(await mockFuture(PermissionStatus.limited).isDenied, false); expect( - await mockFuture(PermissionStatus.permanentlyDenied).isDenied, false); + await mockFuture(PermissionStatus.permanentlyDenied).isDenied, + false, + ); expect(await mockFuture(PermissionStatus.provisional).isDenied, false); }); }); diff --git a/permission_handler_platform_interface/test/src/permissions_test.dart b/permission_handler_platform_interface/test/src/permissions_test.dart index 0f8beb470..2c388d807 100644 --- a/permission_handler_platform_interface/test/src/permissions_test.dart +++ b/permission_handler_platform_interface/test/src/permissions_test.dart @@ -32,47 +32,42 @@ void main() { }); test( - // ignore: lines_longer_than_80_chars - 'equality operator should return true for two instances with the same values', - () { - // Arrange - final firstPermission = Permission.byValue(1); - final secondPermission = Permission.byValue(1); + // ignore: lines_longer_than_80_chars + 'equality operator should return true for two instances with the same values', + () { + // Arrange + final firstPermission = Permission.byValue(1); + final secondPermission = Permission.byValue(1); - // Act & Assert - expect( - firstPermission == secondPermission, - true, - ); - }); + // Act & Assert + expect(firstPermission == secondPermission, true); + }, + ); test( - // ignore: lines_longer_than_80_chars - 'equality operator should return false for two instances with different values', - () { - // Arrange - final firstPermission = Permission.byValue(1); - final secondPermission = Permission.byValue(2); + // ignore: lines_longer_than_80_chars + 'equality operator should return false for two instances with different values', + () { + // Arrange + final firstPermission = Permission.byValue(1); + final secondPermission = Permission.byValue(2); - // Act & Assert - expect( - firstPermission == secondPermission, - false, - ); - }); + // Act & Assert + expect(firstPermission == secondPermission, false); + }, + ); - test('hashCode should be the same for two instances with the same values', - () { - // Arrange - final firstPermission = Permission.byValue(1); - final secondPermission = Permission.byValue(1); + test( + 'hashCode should be the same for two instances with the same values', + () { + // Arrange + final firstPermission = Permission.byValue(1); + final secondPermission = Permission.byValue(1); - // Act & Assert - expect( - firstPermission.hashCode, - secondPermission.hashCode, - ); - }); + // Act & Assert + expect(firstPermission.hashCode, secondPermission.hashCode); + }, + ); test('hashCode should not match for two instances with different values', () { // Arrange @@ -80,9 +75,6 @@ void main() { final secondPermission = Permission.byValue(2); // Act & Assert - expect( - firstPermission.hashCode == secondPermission.hashCode, - false, - ); + expect(firstPermission.hashCode == secondPermission.hashCode, false); }); } diff --git a/permission_handler_platform_interface/test/src/service_status_test.dart b/permission_handler_platform_interface/test/src/service_status_test.dart index b5db02424..6dad5489c 100644 --- a/permission_handler_platform_interface/test/src/service_status_test.dart +++ b/permission_handler_platform_interface/test/src/service_status_test.dart @@ -26,13 +26,17 @@ void main() { }); test( - // ignore: lines_longer_than_80_chars - 'statusByValue should return right index int that corresponds with the right PermissionStatus', - () { - expect(ServiceStatusValue.statusByValue(0), ServiceStatus.disabled); - expect(ServiceStatusValue.statusByValue(1), ServiceStatus.enabled); - expect(ServiceStatusValue.statusByValue(2), ServiceStatus.notApplicable); - }); + // ignore: lines_longer_than_80_chars + 'statusByValue should return right index int that corresponds with the right PermissionStatus', + () { + expect(ServiceStatusValue.statusByValue(0), ServiceStatus.disabled); + expect(ServiceStatusValue.statusByValue(1), ServiceStatus.enabled); + expect( + ServiceStatusValue.statusByValue(2), + ServiceStatus.notApplicable, + ); + }, + ); }); group('ServiceStatusGetters', () { diff --git a/permission_handler_windows/example/lib/main.dart b/permission_handler_windows/example/lib/main.dart index 58a4dc053..7c5a5522a 100644 --- a/permission_handler_windows/example/lib/main.dart +++ b/permission_handler_windows/example/lib/main.dart @@ -3,24 +3,30 @@ import 'package:flutter/material.dart'; import 'package:permission_handler_platform_interface/permission_handler_platform_interface.dart'; void main() { - runApp(BaseflowPluginExample( + runApp( + BaseflowPluginExample( pluginName: 'Permission Handler', githubURL: 'https://github.com/Baseflow/flutter-permission-handler', pubDevURL: 'https://pub.dev/packages/permission_handler', - pages: [PermissionHandlerWidget.createPage()])); + pages: [PermissionHandlerWidget.createPage()], + ), + ); } ///Defines the main theme color final MaterialColor themeMaterialColor = BaseflowPluginExample.createMaterialColor( - const Color.fromRGBO(48, 49, 60, 1)); + const Color.fromRGBO(48, 49, 60, 1), + ); /// A Flutter application demonstrating the functionality of this plugin class PermissionHandlerWidget extends StatefulWidget { /// Create a page containing the functionality of this plugin static ExamplePage createPage() { return ExamplePage( - Icons.location_on, (context) => PermissionHandlerWidget()); + Icons.location_on, + (context) => PermissionHandlerWidget(), + ); } @override @@ -33,18 +39,19 @@ class _PermissionHandlerWidgetState extends State { Widget build(BuildContext context) { return Center( child: ListView( - children: Permission.values - .where((permission) { - return permission != Permission.unknown && - permission != Permission.mediaLibrary && - permission != Permission.photos && - permission != Permission.photosAddOnly && - permission != Permission.reminders && - permission != Permission.appTrackingTransparency && - permission != Permission.criticalAlerts; - }) - .map((permission) => PermissionWidget(permission)) - .toList()), + children: Permission.values + .where((permission) { + return permission != Permission.unknown && + permission != Permission.mediaLibrary && + permission != Permission.photos && + permission != Permission.photosAddOnly && + permission != Permission.reminders && + permission != Permission.appTrackingTransparency && + permission != Permission.criticalAlerts; + }) + .map((permission) => PermissionWidget(permission)) + .toList(), + ), ); } } @@ -106,14 +113,14 @@ class _PermissionState extends State { ), trailing: (_permission is PermissionWithService) ? IconButton( - icon: const Icon( - Icons.info, - color: Colors.white, - ), + icon: const Icon(Icons.info, color: Colors.white), onPressed: () { checkServiceStatus( - context, _permission as PermissionWithService); - }) + context, + _permission as PermissionWithService, + ); + }, + ) : null, onTap: () { requestPermission(_permission); @@ -122,11 +129,16 @@ class _PermissionState extends State { } void checkServiceStatus( - BuildContext context, PermissionWithService permission) async { - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text( - (await _permissionHandler.checkServiceStatus(permission)).toString()), - )); + BuildContext context, + PermissionWithService permission, + ) async { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + (await _permissionHandler.checkServiceStatus(permission)).toString(), + ), + ), + ); } Future requestPermission(Permission permission) async { From c1d0ac1770d73a33ce801ca699ab43f625b7ba0f Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 3 Jun 2026 12:05:24 +0200 Subject: [PATCH 18/57] Update to use monorepo for managing development --- .../Package.swift | 32 +++++++++++++++++++ .../FlutterGeneratedPluginSwiftPackage.swift | 3 ++ .../Flutter/ephemeral/flutter_lldb_helper.py | 32 +++++++++++++++++++ .../ios/Flutter/ephemeral/flutter_lldbinit | 5 +++ .../ephemeral/flutter_native_integration.env | 12 +++++++ permission_handler/example/pubspec.yaml | 4 ++- permission_handler/pubspec.yaml | 3 +- permission_handler_android/pubspec.yaml | 3 +- permission_handler_apple/pubspec.yaml | 7 ++-- permission_handler_html/pubspec.yaml | 7 ++-- .../pubspec.yaml | 3 +- permission_handler_windows/pubspec.yaml | 5 +-- pubspec.yaml | 13 ++++++++ 13 files changed, 117 insertions(+), 12 deletions(-) create mode 100644 permission_handler/example/ios/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage/Package.swift create mode 100644 permission_handler/example/ios/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage/Sources/FlutterGeneratedPluginSwiftPackage/FlutterGeneratedPluginSwiftPackage.swift create mode 100644 permission_handler/example/ios/Flutter/ephemeral/flutter_lldb_helper.py create mode 100644 permission_handler/example/ios/Flutter/ephemeral/flutter_lldbinit create mode 100644 permission_handler/example/ios/Flutter/ephemeral/flutter_native_integration.env create mode 100644 pubspec.yaml diff --git a/permission_handler/example/ios/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage/Package.swift b/permission_handler/example/ios/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage/Package.swift new file mode 100644 index 000000000..41fdeba8c --- /dev/null +++ b/permission_handler/example/ios/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage/Package.swift @@ -0,0 +1,32 @@ +// swift-tools-version: 5.9 +// The swift-tools-version declares the minimum version of Swift required to build this package. +// +// Generated file. Do not edit. +// + +import PackageDescription + +let package = Package( + name: "FlutterGeneratedPluginSwiftPackage", + platforms: [ + .iOS("13.0") + ], + products: [ + .library(name: "FlutterGeneratedPluginSwiftPackage", type: .static, targets: ["FlutterGeneratedPluginSwiftPackage"]) + ], + dependencies: [ + .package(name: "permission_handler_apple", path: "../.packages/permission_handler_apple"), + .package(name: "url_launcher_ios", path: "../.packages/url_launcher_ios-6.4.1"), + .package(name: "FlutterFramework", path: "../.packages/FlutterFramework") + ], + targets: [ + .target( + name: "FlutterGeneratedPluginSwiftPackage", + dependencies: [ + .product(name: "permission-handler-apple", package: "permission_handler_apple"), + .product(name: "url-launcher-ios", package: "url_launcher_ios"), + .product(name: "FlutterFramework", package: "FlutterFramework") + ] + ) + ] +) diff --git a/permission_handler/example/ios/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage/Sources/FlutterGeneratedPluginSwiftPackage/FlutterGeneratedPluginSwiftPackage.swift b/permission_handler/example/ios/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage/Sources/FlutterGeneratedPluginSwiftPackage/FlutterGeneratedPluginSwiftPackage.swift new file mode 100644 index 000000000..a30d95a81 --- /dev/null +++ b/permission_handler/example/ios/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage/Sources/FlutterGeneratedPluginSwiftPackage/FlutterGeneratedPluginSwiftPackage.swift @@ -0,0 +1,3 @@ +// +// Generated file. Do not edit. +// diff --git a/permission_handler/example/ios/Flutter/ephemeral/flutter_lldb_helper.py b/permission_handler/example/ios/Flutter/ephemeral/flutter_lldb_helper.py new file mode 100644 index 000000000..a88caf99d --- /dev/null +++ b/permission_handler/example/ios/Flutter/ephemeral/flutter_lldb_helper.py @@ -0,0 +1,32 @@ +# +# Generated file, do not edit. +# + +import lldb + +def handle_new_rx_page(frame: lldb.SBFrame, bp_loc, extra_args, intern_dict): + """Intercept NOTIFY_DEBUGGER_ABOUT_RX_PAGES and touch the pages.""" + base = frame.register["x0"].GetValueAsAddress() + page_len = frame.register["x1"].GetValueAsUnsigned() + + # Note: NOTIFY_DEBUGGER_ABOUT_RX_PAGES will check contents of the + # first page to see if handled it correctly. This makes diagnosing + # misconfiguration (e.g. missing breakpoint) easier. + data = bytearray(page_len) + data[0:8] = b'IHELPED!' + + error = lldb.SBError() + frame.GetThread().GetProcess().WriteMemory(base, data, error) + if not error.Success(): + print(f'Failed to write into {base}[+{page_len}]', error) + return + +def __lldb_init_module(debugger: lldb.SBDebugger, _): + target = debugger.GetDummyTarget() + # Caveat: must use BreakpointCreateByRegEx here and not + # BreakpointCreateByName. For some reasons callback function does not + # get carried over from dummy target for the later. + bp = target.BreakpointCreateByRegex("^NOTIFY_DEBUGGER_ABOUT_RX_PAGES$") + bp.SetScriptCallbackFunction('{}.handle_new_rx_page'.format(__name__)) + bp.SetAutoContinue(True) + print("-- LLDB integration loaded --") diff --git a/permission_handler/example/ios/Flutter/ephemeral/flutter_lldbinit b/permission_handler/example/ios/Flutter/ephemeral/flutter_lldbinit new file mode 100644 index 000000000..e3ba6fbed --- /dev/null +++ b/permission_handler/example/ios/Flutter/ephemeral/flutter_lldbinit @@ -0,0 +1,5 @@ +# +# Generated file, do not edit. +# + +command script import --relative-to-command-file flutter_lldb_helper.py diff --git a/permission_handler/example/ios/Flutter/ephemeral/flutter_native_integration.env b/permission_handler/example/ios/Flutter/ephemeral/flutter_native_integration.env new file mode 100644 index 000000000..89be47305 --- /dev/null +++ b/permission_handler/example/ios/Flutter/ephemeral/flutter_native_integration.env @@ -0,0 +1,12 @@ +FLUTTER_ROOT=/Users/au662726/fvm/versions/main +FLUTTER_APPLICATION_PATH=/Users/au662726/github_projects/flutter-permission-handler/permission_handler/example +FLUTTER_FRAMEWORK_SWIFT_PACKAGE_PATH=/Users/au662726/github_projects/flutter-permission-handler/permission_handler/example/ios/Flutter/ephemeral/Packages/.packages/FlutterFramework +COCOAPODS_PARALLEL_CODE_SIGN=true +FLUTTER_TARGET=lib/main.dart +FLUTTER_BUILD_DIR=build +FLUTTER_BUILD_NAME=1.0.0 +FLUTTER_BUILD_NUMBER=1 +DART_OBFUSCATION=false +TRACK_WIDGET_CREATION=true +TREE_SHAKE_ICONS=false +PACKAGE_CONFIG=.dart_tool/package_config.json diff --git a/permission_handler/example/pubspec.yaml b/permission_handler/example/pubspec.yaml index 8ea895146..c3627eebb 100644 --- a/permission_handler/example/pubspec.yaml +++ b/permission_handler/example/pubspec.yaml @@ -2,7 +2,9 @@ name: permission_handler_example description: Demonstrates how to use the permission_handler plugin. environment: - sdk: ^3.7.0 + sdk: ^3.6.0 + flutter: ">=3.24.0" +resolution: workspace dependencies: baseflow_plugin_template: ^2.1.1 diff --git a/permission_handler/pubspec.yaml b/permission_handler/pubspec.yaml index 7f8b93f42..d720f281c 100644 --- a/permission_handler/pubspec.yaml +++ b/permission_handler/pubspec.yaml @@ -5,8 +5,9 @@ issue_tracker: https://github.com/Baseflow/flutter-permission-handler/issues version: 13.0.1 environment: - sdk: ^3.5.0 + sdk: ^3.6.0 flutter: ">=3.24.0" +resolution: workspace flutter: plugin: diff --git a/permission_handler_android/pubspec.yaml b/permission_handler_android/pubspec.yaml index efd02930e..a60c3ed14 100644 --- a/permission_handler_android/pubspec.yaml +++ b/permission_handler_android/pubspec.yaml @@ -4,8 +4,9 @@ homepage: https://github.com/baseflow/flutter-permission-handler version: 14.0.1 environment: - sdk: ^3.5.0 + sdk: ^3.6.0 flutter: ">=3.24.0" +resolution: workspace flutter: plugin: diff --git a/permission_handler_apple/pubspec.yaml b/permission_handler_apple/pubspec.yaml index a03947478..d913c67b8 100644 --- a/permission_handler_apple/pubspec.yaml +++ b/permission_handler_apple/pubspec.yaml @@ -5,8 +5,9 @@ issue_tracker: https://github.com/Baseflow/flutter-permission-handler/issues version: 9.4.9 environment: - sdk: ">=2.18.0 <4.0.0" - flutter: ">=3.3.0" + sdk: ^3.6.0 + flutter: ">=3.24.0" +resolution: workspace flutter: plugin: @@ -21,5 +22,5 @@ dependencies: permission_handler_platform_interface: ^4.2.0 dev_dependencies: - flutter_lints: ^1.0.4 + flutter_lints: ^5.0.0 plugin_platform_interface: ^2.0.0 diff --git a/permission_handler_html/pubspec.yaml b/permission_handler_html/pubspec.yaml index 92d8fb40f..7af165520 100644 --- a/permission_handler_html/pubspec.yaml +++ b/permission_handler_html/pubspec.yaml @@ -5,8 +5,9 @@ version: 0.1.4+0 homepage: https://github.com/baseflow/flutter-permission-handler environment: - sdk: ">=3.3.0 <4.0.0" - flutter: ">=3.16.0" + sdk: ^3.5.0 + flutter: ">=3.24.0" +resolution: workspace dependencies: flutter: @@ -19,7 +20,7 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - flutter_lints: ^2.0.0 + flutter_lints: ^5.0.0 mockito: ^5.4.2 build_runner: ^2.1.2 test: ^1.24.4 diff --git a/permission_handler_platform_interface/pubspec.yaml b/permission_handler_platform_interface/pubspec.yaml index 665dac0b0..157c686d5 100644 --- a/permission_handler_platform_interface/pubspec.yaml +++ b/permission_handler_platform_interface/pubspec.yaml @@ -6,8 +6,9 @@ homepage: https://github.com/baseflow/flutter-permission-handler/tree/master/per version: 4.3.2 environment: - sdk: ^3.5.0 + sdk: ^3.6.0 flutter: ">=3.24.0" +resolution: workspace dependencies: flutter: diff --git a/permission_handler_windows/pubspec.yaml b/permission_handler_windows/pubspec.yaml index 3495a07b7..b01412999 100644 --- a/permission_handler_windows/pubspec.yaml +++ b/permission_handler_windows/pubspec.yaml @@ -21,5 +21,6 @@ dev_dependencies: plugin_platform_interface: ^2.0.0 environment: - sdk: ">=2.12.0 <4.0.0" - flutter: ">=2.0.0" + sdk: ^3.6.0 + flutter: ">=3.24.0" +resolution: workspace diff --git a/pubspec.yaml b/pubspec.yaml new file mode 100644 index 000000000..4a51ba2ae --- /dev/null +++ b/pubspec.yaml @@ -0,0 +1,13 @@ +name: _ +publish_to: none +environment: + sdk: ^3.6.0 + flutter: ">=3.24.0" +workspace: + - permission_handler + - permission_handler/example + - permission_handler_android + - permission_handler_apple + - permission_handler_html + - permission_handler_platform_interface + - permission_handler_windows From 88ca052c8a2f795f9cc3e5047970d8708682fd6f Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 3 Jun 2026 12:33:53 +0200 Subject: [PATCH 19/57] Linting, formatting, fix analysis issues --- permission_handler/example/lib/main.dart | 4 +- permission_handler/example/pubspec.yaml | 1 + .../test/permission_handler_test.dart | 3 +- .../example/lib/main.dart | 52 +++++++------ .../example/pubspec.yaml | 11 +-- .../example/lib/main.dart | 76 ++++++++++--------- permission_handler_apple/example/pubspec.yaml | 14 ++-- permission_handler_html/example/lib/main.dart | 22 +++--- permission_handler_html/example/pubspec.yaml | 5 +- .../lib/permission_handler_html.dart | 2 +- permission_handler_html/lib/web_delegate.dart | 26 ++++--- ...ethod_channel_permission_handler_test.dart | 16 ++-- .../src/method_channel/utils/coded_test.dart | 3 +- ...ssion_handler_platform_interface_test.dart | 3 +- .../example/lib/main.dart | 44 +++++++---- .../example/pubspec.yaml | 62 +++++++-------- pubspec.yaml | 10 ++- 17 files changed, 187 insertions(+), 167 deletions(-) diff --git a/permission_handler/example/lib/main.dart b/permission_handler/example/lib/main.dart index 7a6ab62bc..9dbe35a1d 100644 --- a/permission_handler/example/lib/main.dart +++ b/permission_handler/example/lib/main.dart @@ -18,8 +18,8 @@ void main() { ///Defines the main theme color final MaterialColor themeMaterialColor = BaseflowPluginExample.createMaterialColor( - const Color.fromRGBO(48, 49, 60, 1), - ); + const Color.fromRGBO(48, 49, 60, 1), +); /// A Flutter application demonstrating the functionality of this plugin class PermissionHandlerWidget extends StatefulWidget { diff --git a/permission_handler/example/pubspec.yaml b/permission_handler/example/pubspec.yaml index c3627eebb..4b6545123 100644 --- a/permission_handler/example/pubspec.yaml +++ b/permission_handler/example/pubspec.yaml @@ -22,6 +22,7 @@ dev_dependencies: flutter_test: sdk: flutter url_launcher: ^6.3.1 + flutter_lints: ^5.0.0 flutter: uses-material-design: true diff --git a/permission_handler/test/permission_handler_test.dart b/permission_handler/test/permission_handler_test.dart index 4b51c142c..66ddfae12 100644 --- a/permission_handler/test/permission_handler_test.dart +++ b/permission_handler/test/permission_handler_test.dart @@ -178,7 +178,8 @@ class MockPermissionHandlerPlatform extends Mock with // ignore: prefer_mixin MockPlatformInterfaceMixin - implements PermissionHandlerPlatform { + implements + PermissionHandlerPlatform { @override Future checkPermissionStatus(Permission permission) => Future.value(PermissionStatus.granted); diff --git a/permission_handler_android/example/lib/main.dart b/permission_handler_android/example/lib/main.dart index f8f49b03d..4a0a6e052 100644 --- a/permission_handler_android/example/lib/main.dart +++ b/permission_handler_android/example/lib/main.dart @@ -42,20 +42,21 @@ class _PermissionHandlerWidgetState extends State { Widget build(BuildContext context) { return Center( child: ListView( - children: Permission.values - .where((permission) { - return permission != Permission.unknown && - permission != Permission.mediaLibrary && - permission != Permission.photosAddOnly && - permission != Permission.reminders && - permission != Permission.bluetooth && - permission != Permission.appTrackingTransparency && - permission != Permission.criticalAlerts && - permission != Permission.assistant && - permission != Permission.backgroundRefresh; - }) - .map((permission) => PermissionWidget(permission)) - .toList(), + children: + Permission.values + .where((permission) { + return permission != Permission.unknown && + permission != Permission.mediaLibrary && + permission != Permission.photosAddOnly && + permission != Permission.reminders && + permission != Permission.bluetooth && + permission != Permission.appTrackingTransparency && + permission != Permission.criticalAlerts && + permission != Permission.assistant && + permission != Permission.backgroundRefresh; + }) + .map((permission) => PermissionWidget(permission)) + .toList(), ), ); } @@ -117,17 +118,18 @@ class _PermissionState extends State { _permissionStatus.toString(), style: TextStyle(color: getPermissionColor()), ), - trailing: (widget._permission is PermissionWithService) - ? IconButton( - icon: const Icon(Icons.info, color: Colors.white), - onPressed: () { - checkServiceStatus( - context, - widget._permission as PermissionWithService, - ); - }, - ) - : null, + trailing: + (widget._permission is PermissionWithService) + ? IconButton( + icon: const Icon(Icons.info, color: Colors.white), + onPressed: () { + checkServiceStatus( + context, + widget._permission as PermissionWithService, + ); + }, + ) + : null, onTap: () { requestPermission(widget._permission); }, diff --git a/permission_handler_android/example/pubspec.yaml b/permission_handler_android/example/pubspec.yaml index e76011501..22839e1ae 100644 --- a/permission_handler_android/example/pubspec.yaml +++ b/permission_handler_android/example/pubspec.yaml @@ -3,6 +3,7 @@ description: Demonstrates how to use the permission_handler_android plugin. environment: sdk: ^3.7.0 +resolution: workspace dependencies: baseflow_plugin_template: ^2.1.2 @@ -13,14 +14,8 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - - permission_handler_android: - # When depending on this package from a real application you should use: - # permission_handler_android: ^x.y.z - # See https://dart.dev/tools/pub/dependencies#version-constraints - # The example app is bundled with the plugin so we use a path dependency on - # the parent directory to use the current plugin's version. - path: ../ + flutter_lints: ^5.0.0 + permission_handler_android: ^14.0.1 url_launcher: ^6.0.12 diff --git a/permission_handler_apple/example/lib/main.dart b/permission_handler_apple/example/lib/main.dart index 7605e3c48..ae9563d62 100644 --- a/permission_handler_apple/example/lib/main.dart +++ b/permission_handler_apple/example/lib/main.dart @@ -32,38 +32,39 @@ class PermissionHandlerWidget extends StatefulWidget { } @override - _PermissionHandlerWidgetState createState() => - _PermissionHandlerWidgetState(); + PermissionHandlerWidgetState createState() => PermissionHandlerWidgetState(); } -class _PermissionHandlerWidgetState extends State { +/// The state of the [PermissionHandlerWidget] that listens for permission status changes. +class PermissionHandlerWidgetState extends State { @override Widget build(BuildContext context) { return Center( child: ListView( - children: Permission.values - .where((permission) { - return permission != Permission.unknown && - permission != Permission.phone && - permission != Permission.sms && - permission != Permission.ignoreBatteryOptimizations && - permission != Permission.accessMediaLocation && - permission != Permission.activityRecognition && - permission != Permission.manageExternalStorage && - permission != Permission.systemAlertWindow && - permission != Permission.requestInstallPackages && - permission != Permission.accessNotificationPolicy && - permission != Permission.bluetoothScan && - permission != Permission.bluetoothAdvertise && - permission != Permission.bluetoothConnect && - permission != Permission.nearbyWifiDevices && - permission != Permission.videos && - permission != Permission.audio && - permission != Permission.scheduleExactAlarm && - permission != Permission.sensorsAlways; - }) - .map((permission) => PermissionWidget(permission)) - .toList(), + children: + Permission.values + .where((permission) { + return permission != Permission.unknown && + permission != Permission.phone && + permission != Permission.sms && + permission != Permission.ignoreBatteryOptimizations && + permission != Permission.accessMediaLocation && + permission != Permission.activityRecognition && + permission != Permission.manageExternalStorage && + permission != Permission.systemAlertWindow && + permission != Permission.requestInstallPackages && + permission != Permission.accessNotificationPolicy && + permission != Permission.bluetoothScan && + permission != Permission.bluetoothAdvertise && + permission != Permission.bluetoothConnect && + permission != Permission.nearbyWifiDevices && + permission != Permission.videos && + permission != Permission.audio && + permission != Permission.scheduleExactAlarm && + permission != Permission.sensorsAlways; + }) + .map((permission) => PermissionWidget(permission)) + .toList(), ), ); } @@ -124,17 +125,18 @@ class _PermissionState extends State { _permissionStatus.toString(), style: TextStyle(color: getPermissionColor()), ), - trailing: (widget.permission is PermissionWithService) - ? IconButton( - icon: const Icon(Icons.info, color: Colors.white), - onPressed: () { - checkServiceStatus( - context, - widget.permission as PermissionWithService, - ); - }, - ) - : null, + trailing: + (widget.permission is PermissionWithService) + ? IconButton( + icon: const Icon(Icons.info, color: Colors.white), + onPressed: () { + checkServiceStatus( + context, + widget.permission as PermissionWithService, + ); + }, + ) + : null, onTap: () { requestPermission(widget.permission); }, diff --git a/permission_handler_apple/example/pubspec.yaml b/permission_handler_apple/example/pubspec.yaml index 71aaacd79..042d6ae27 100644 --- a/permission_handler_apple/example/pubspec.yaml +++ b/permission_handler_apple/example/pubspec.yaml @@ -3,23 +3,21 @@ description: Demonstrates how to use the permission_handler_apple plugin. environment: sdk: ^3.7.0 + flutter: ">=3.24.0" dependencies: baseflow_plugin_template: ^2.1.1 + permission_handler_apple: ^9.4.9 + permission_handler_platform_interface: ^4.3.2 flutter: sdk: flutter +resolution: workspace + dev_dependencies: flutter_test: sdk: flutter - - permission_handler_apple: - # When depending on this package from a real application you should use: - # permission_handler: ^x.y.z - # See https://dart.dev/tools/pub/dependencies#version-constraints - # The example app is bundled with the plugin so we use a path dependency on - # the parent directory to use the current plugin's version. - path: ../ + flutter_lints: ^5.0.0 url_launcher: ^6.3.2 diff --git a/permission_handler_html/example/lib/main.dart b/permission_handler_html/example/lib/main.dart index 37ffcf5b3..3cc3d0b5b 100644 --- a/permission_handler_html/example/lib/main.dart +++ b/permission_handler_html/example/lib/main.dart @@ -16,8 +16,8 @@ void main() { ///Defines the main theme color final MaterialColor themeMaterialColor = BaseflowPluginExample.createMaterialColor( - const Color.fromRGBO(48, 49, 60, 1), - ); + const Color.fromRGBO(48, 49, 60, 1), +); /// A Flutter application demonstrating the functionality of this plugin class PermissionHandlerWidget extends StatefulWidget { @@ -85,9 +85,7 @@ class _PermissionState extends State { } void _listenForPermissionStatus() async { - await _permissionHandler - .checkPermissionStatus(widget._permission) - .then( + await _permissionHandler.checkPermissionStatus(widget._permission).then( (status) => setState(() => _permissionStatus = status), onError: (error, st) => debugPrint('$error'), ); @@ -148,13 +146,11 @@ class _PermissionState extends State { } Future requestPermission(Permission permission) async { - await _permissionHandler - .requestPermissions([permission]) - .then( - (status) => setState(() { - _permissionStatus = status[permission] ?? PermissionStatus.denied; - }), - onError: (error, st) => debugPrint('$error'), - ); + await _permissionHandler.requestPermissions([permission]).then( + (status) => setState(() { + _permissionStatus = status[permission] ?? PermissionStatus.denied; + }), + onError: (error, st) => debugPrint('$error'), + ); } } diff --git a/permission_handler_html/example/pubspec.yaml b/permission_handler_html/example/pubspec.yaml index f380c161a..122092b5b 100644 --- a/permission_handler_html/example/pubspec.yaml +++ b/permission_handler_html/example/pubspec.yaml @@ -2,8 +2,10 @@ name: permission_handler_html_example description: Demonstrates how to use the permission_handler_html plugin. environment: - sdk: ">=3.0.5 <4.0.0" + sdk: ^3.6.0 + flutter: ">=3.24.0" +resolution: workspace dependencies: permission_handler_platform_interface: ^4.2.0 baseflow_plugin_template: ^2.1.2 @@ -15,6 +17,7 @@ dev_dependencies: sdk: flutter flutter_test: sdk: flutter + flutter_lints: ^5.0.0 permission_handler_html: # When depending on this package from a real application you should use: diff --git a/permission_handler_html/lib/permission_handler_html.dart b/permission_handler_html/lib/permission_handler_html.dart index db6b28d37..05b8afa0a 100644 --- a/permission_handler_html/lib/permission_handler_html.dart +++ b/permission_handler_html/lib/permission_handler_html.dart @@ -39,7 +39,7 @@ class WebPermissionHandler extends PermissionHandlerPlatform { /// Constructs a WebPermissionHandler. WebPermissionHandler({required WebDelegate webDelegate}) - : _webDelegate = webDelegate; + : _webDelegate = webDelegate; @override Future> requestPermissions( diff --git a/permission_handler_html/lib/web_delegate.dart b/permission_handler_html/lib/web_delegate.dart index e9a381ece..0736ab310 100644 --- a/permission_handler_html/lib/web_delegate.dart +++ b/permission_handler_html/lib/web_delegate.dart @@ -13,9 +13,9 @@ class WebDelegate { web.MediaDevices? devices, web.Geolocation? geolocation, web.Permissions? permissions, - ) : _devices = devices, - _geolocation = geolocation, - _htmlPermissions = permissions; + ) : _devices = devices, + _geolocation = geolocation, + _htmlPermissions = permissions; /// The html media devices object used to request camera and microphone permissions. final web.MediaDevices? _devices; @@ -93,8 +93,10 @@ class WebDelegate { audioTracks[0].stop(); } } - } on web.DOMException { - return false; + } catch (e) { + if (e.isA()) { + return false; + } } return true; @@ -123,8 +125,10 @@ class WebDelegate { videoTracks[0].stop(); } } - } on web.DOMException { - return false; + } catch (e) { + if (e.isA()) { + return false; + } } return true; @@ -132,8 +136,8 @@ class WebDelegate { Future _requestNotificationPermission() async { return web.Notification.requestPermission().toDart.then( - (permission) => (permission == "granted".toJS), - ); + (permission) => (permission == "granted".toJS), + ); } Future _requestLocationPermission() async { @@ -162,8 +166,8 @@ class WebDelegate { Permission.notification => await _requestNotificationPermission(), Permission.location => await _requestLocationPermission(), _ => throw UnsupportedError( - 'The ${permission.toString()} permission is currently not supported on web.', - ), + 'The ${permission.toString()} permission is currently not supported on web.', + ), }; if (!permissionGranted) { diff --git a/permission_handler_platform_interface/test/src/method_channel/method_channel_permission_handler_test.dart b/permission_handler_platform_interface/test/src/method_channel/method_channel_permission_handler_test.dart index 67def69d1..b39410a65 100644 --- a/permission_handler_platform_interface/test/src/method_channel/method_channel_permission_handler_test.dart +++ b/permission_handler_platform_interface/test/src/method_channel/method_channel_permission_handler_test.dart @@ -4,10 +4,10 @@ import 'package:permission_handler_platform_interface/src/method_channel/method_ import 'method_channel_mock.dart'; List get mockPermissions => List.of({ - Permission.contacts, - Permission.camera, - Permission.calendarWriteOnly, -}); + Permission.contacts, + Permission.camera, + Permission.calendarWriteOnly, + }); Map get mockPermissionMap => {}; @@ -159,8 +159,8 @@ void main() { result: true, ); - final hasOpenedAppSettings = await MethodChannelPermissionHandler() - .openAppSettings(); + final hasOpenedAppSettings = + await MethodChannelPermissionHandler().openAppSettings(); expect(hasOpenedAppSettings, true); }); @@ -172,8 +172,8 @@ void main() { result: false, ); - final hasOpenedAppSettings = await MethodChannelPermissionHandler() - .openAppSettings(); + final hasOpenedAppSettings = + await MethodChannelPermissionHandler().openAppSettings(); expect(hasOpenedAppSettings, false); }); diff --git a/permission_handler_platform_interface/test/src/method_channel/utils/coded_test.dart b/permission_handler_platform_interface/test/src/method_channel/utils/coded_test.dart index b9037c2b0..2932a6406 100644 --- a/permission_handler_platform_interface/test/src/method_channel/utils/coded_test.dart +++ b/permission_handler_platform_interface/test/src/method_channel/utils/coded_test.dart @@ -12,7 +12,8 @@ void main() { expect(decodeServiceStatus(0), ServiceStatus.disabled); }); - test('decodePermissionRequestResult should convert a map' + test( + 'decodePermissionRequestResult should convert a map' 'to map', () { var value = {1: 1}; diff --git a/permission_handler_platform_interface/test/src/permission_handler_platform_interface_test.dart b/permission_handler_platform_interface/test/src/permission_handler_platform_interface_test.dart index 3977d648b..157602eef 100644 --- a/permission_handler_platform_interface/test/src/permission_handler_platform_interface_test.dart +++ b/permission_handler_platform_interface/test/src/permission_handler_platform_interface_test.dart @@ -111,4 +111,5 @@ class MockPermissionHandlerPlatform extends Mock with // ignore: prefer_mixin MockPlatformInterfaceMixin - implements PermissionHandlerPlatform {} + implements + PermissionHandlerPlatform {} diff --git a/permission_handler_windows/example/lib/main.dart b/permission_handler_windows/example/lib/main.dart index 7c5a5522a..4e5f30ca1 100644 --- a/permission_handler_windows/example/lib/main.dart +++ b/permission_handler_windows/example/lib/main.dart @@ -1,3 +1,5 @@ +// ignore_for_file: avoid_print + import 'package:baseflow_plugin_template/baseflow_plugin_template.dart'; import 'package:flutter/material.dart'; import 'package:permission_handler_platform_interface/permission_handler_platform_interface.dart'; @@ -16,11 +18,14 @@ void main() { ///Defines the main theme color final MaterialColor themeMaterialColor = BaseflowPluginExample.createMaterialColor( - const Color.fromRGBO(48, 49, 60, 1), - ); + const Color.fromRGBO(48, 49, 60, 1), +); /// A Flutter application demonstrating the functionality of this plugin class PermissionHandlerWidget extends StatefulWidget { + /// Creates a [PermissionHandlerWidget] that listens for permission status changes. + const PermissionHandlerWidget({super.key}); + /// Create a page containing the functionality of this plugin static ExamplePage createPage() { return ExamplePage( @@ -30,11 +35,11 @@ class PermissionHandlerWidget extends StatefulWidget { } @override - _PermissionHandlerWidgetState createState() => - _PermissionHandlerWidgetState(); + PermissionHandlerWidgetState createState() => PermissionHandlerWidgetState(); } -class _PermissionHandlerWidgetState extends State { +/// State for the [PermissionHandlerWidget] that listens for permission status changes. +class PermissionHandlerWidgetState extends State { @override Widget build(BuildContext context) { return Center( @@ -59,18 +64,21 @@ class _PermissionHandlerWidgetState extends State { /// Permission widget containing information about the passed [Permission] class PermissionWidget extends StatefulWidget { /// Constructs a [PermissionWidget] for the supplied [Permission] - const PermissionWidget(this._permission); + const PermissionWidget(this._permission, {super.key}); final Permission _permission; + /// Returns the [Permission] associated with this widget. + Permission get permission => _permission; + @override - _PermissionState createState() => _PermissionState(_permission); + PermissionWidgetState createState() => PermissionWidgetState(); } -class _PermissionState extends State { - _PermissionState(this._permission); - - final Permission _permission; +/// State for the [PermissionWidget] that listens for permission status changes. +class PermissionWidgetState extends State { + /// Constructs a [PermissionWidgetState] for the supplied [PermissionWidget]. + PermissionWidgetState(); final PermissionHandlerPlatform _permissionHandler = PermissionHandlerPlatform.instance; PermissionStatus _permissionStatus = PermissionStatus.denied; @@ -83,10 +91,12 @@ class _PermissionState extends State { } void _listenForPermissionStatus() async { - final status = await _permissionHandler.checkPermissionStatus(_permission); + final status = + await _permissionHandler.checkPermissionStatus(widget.permission); setState(() => _permissionStatus = status); } + /// Returns the color to use for the permission status. Color getPermissionColor() { switch (_permissionStatus) { case PermissionStatus.denied: @@ -104,30 +114,31 @@ class _PermissionState extends State { Widget build(BuildContext context) { return ListTile( title: Text( - _permission.toString(), + widget.permission.toString(), style: Theme.of(context).textTheme.bodyLarge, ), subtitle: Text( _permissionStatus.toString(), style: TextStyle(color: getPermissionColor()), ), - trailing: (_permission is PermissionWithService) + trailing: (widget.permission is PermissionWithService) ? IconButton( icon: const Icon(Icons.info, color: Colors.white), onPressed: () { checkServiceStatus( context, - _permission as PermissionWithService, + widget.permission as PermissionWithService, ); }, ) : null, onTap: () { - requestPermission(_permission); + requestPermission(widget.permission); }, ); } + /// Requests permission for the given [Permission]. void checkServiceStatus( BuildContext context, PermissionWithService permission, @@ -141,6 +152,7 @@ class _PermissionState extends State { ); } + /// Requests permission for the given [Permission]. Future requestPermission(Permission permission) async { final status = await _permissionHandler.requestPermissions([permission]); diff --git a/permission_handler_windows/example/pubspec.yaml b/permission_handler_windows/example/pubspec.yaml index 2deb8e72c..0c9e1d4f5 100644 --- a/permission_handler_windows/example/pubspec.yaml +++ b/permission_handler_windows/example/pubspec.yaml @@ -1,33 +1,29 @@ -name: permission_handler_windows_example -description: Demonstrates how to use the permission_handler_windows plugin. - -environment: - sdk: ">=2.15.0 <3.0.0" - -dependencies: - baseflow_plugin_template: ^2.1.1 - flutter: - sdk: flutter - -dev_dependencies: - flutter_test: - sdk: flutter - - permission_handler_windows: - # When depending on this package from a real application you should use: - # permission_handler_windows: ^x.y.z - # See https://dart.dev/tools/pub/dependencies#version-constraints - # The example app is bundled with the plugin so we use a path dependency on - # the parent directory to use the current plugin's version. - path: ../ - - url_launcher: ^6.0.12 - -flutter: - uses-material-design: true - - assets: - - res/images/baseflow_logo_def_light-02.png - - res/images/poweredByBaseflowLogoLight@3x.png - - packages/baseflow_plugin_template/logo.png - - packages/baseflow_plugin_template/poweredByBaseflow.png +name: permission_handler_windows_example +description: Demonstrates how to use the permission_handler_windows plugin. + +environment: + sdk: ^3.6.0 + flutter: ">=3.24.0" +resolution: workspace + +dependencies: + baseflow_plugin_template: ^2.1.1 + flutter: + sdk: flutter + permission_handler_windows: ^0.2.2 + permission_handler_platform_interface: ^4.1.0 + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^5.0.0 + url_launcher: ^6.0.12 + +flutter: + uses-material-design: true + + assets: + - res/images/baseflow_logo_def_light-02.png + - res/images/poweredByBaseflowLogoLight@3x.png + - packages/baseflow_plugin_template/logo.png + - packages/baseflow_plugin_template/poweredByBaseflow.png diff --git a/pubspec.yaml b/pubspec.yaml index 4a51ba2ae..56e2c0439 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,13 +1,21 @@ -name: _ +name: permission_handler_monorepo publish_to: none environment: sdk: ^3.6.0 flutter: ">=3.24.0" + workspace: - permission_handler - permission_handler/example - permission_handler_android + - permission_handler_android/example - permission_handler_apple + - permission_handler_apple/example - permission_handler_html + - permission_handler_html/example - permission_handler_platform_interface - permission_handler_windows + - permission_handler_windows/example + +dev_dependencies: + flutter_lints: ^5.0.0 From 910859dbea1414e27bf11cdc18df8dc85c4dc01e Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 3 Jun 2026 12:39:14 +0200 Subject: [PATCH 20/57] Fix test for number of permissions --- .../test/src/permissions_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/permission_handler_platform_interface/test/src/permissions_test.dart b/permission_handler_platform_interface/test/src/permissions_test.dart index 2c388d807..78160ddae 100644 --- a/permission_handler_platform_interface/test/src/permissions_test.dart +++ b/permission_handler_platform_interface/test/src/permissions_test.dart @@ -5,7 +5,7 @@ void main() { test('Permission has the right amount of possible Permission values', () { const values = Permission.values; - expect(values.length, 40); + expect(values.length, 41); }); test('check if byValue returns corresponding Permission value', () { From 8cbc4c15025cf311dde1179edb05324b2d8a7767 Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 3 Jun 2026 12:43:08 +0200 Subject: [PATCH 21/57] Build after test (build is more time-costly) --- .github/workflows/permission_handler.yaml | 25 +++++++++++------------ 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/.github/workflows/permission_handler.yaml b/.github/workflows/permission_handler.yaml index 340849441..89a456d75 100644 --- a/.github/workflows/permission_handler.yaml +++ b/.github/workflows/permission_handler.yaml @@ -26,7 +26,7 @@ jobs: # TODO(mvanbeusekom): Manually set to macOS 15 to support Xcode 16 and iOS 18 SDKs. # Currently `macos-latest` is based on macOS 14 and doesn't support iOS 18 SDK. This # should be moved back to `macos-latest` when GitHub Actions images are updated. - runs-on: macos-15 + runs-on: macos-15 env: source-directory: ./permission_handler @@ -62,18 +62,7 @@ jobs: - name: Run Flutter Analyzer run: flutter analyze working-directory: ${{env.source-directory}} - - # Build Android version of the example App - - name: Run Android build - run: flutter build apk --release - working-directory: ${{env.example-directory}} - - # Build iOS version of the example App - - name: Run iOS build - run: flutter build ios --release --no-codesign - working-directory: ${{env.example-directory}} - - # Run all unit-tests with code coverage + # Run all unit-tests with code coverage - name: Run unit tests run: flutter test --coverage working-directory: ${{env.source-directory}} @@ -85,3 +74,13 @@ jobs: file: ${{env.source-directory}}/coverage/lcov.info # optional flags: unittests # optional name: permission_handler # optional + + # Build Android version of the example App + - name: Run Android build + run: flutter build apk --release + working-directory: ${{env.example-directory}} + + # Build iOS version of the example App + - name: Run iOS build + run: flutter build ios --release --no-codesign + working-directory: ${{env.example-directory}} From 5639fb5f1e13c7b487b7cfd50cf46ec5235aa93c Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 3 Jun 2026 12:45:00 +0200 Subject: [PATCH 22/57] Fix permission_handler android build compileSdk --- permission_handler/example/android/app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/permission_handler/example/android/app/build.gradle b/permission_handler/example/android/app/build.gradle index 047e56a5c..25715f826 100644 --- a/permission_handler/example/android/app/build.gradle +++ b/permission_handler/example/android/app/build.gradle @@ -25,7 +25,7 @@ android { if (project.android.hasProperty("namespace")) { namespace 'com.baseflow.permissionhandlerexample' } - compileSdkVersion 36 + compileSdkVersion 37 compileOptions { sourceCompatibility JavaVersion.VERSION_17 From a803e14b260deee4ac670cf5e527919ac20806ec Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 3 Jun 2026 12:50:01 +0200 Subject: [PATCH 23/57] Forgot to bump compilesdk version for android example app --- permission_handler_android/example/android/app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/permission_handler_android/example/android/app/build.gradle b/permission_handler_android/example/android/app/build.gradle index 04ce10422..d740562c6 100644 --- a/permission_handler_android/example/android/app/build.gradle +++ b/permission_handler_android/example/android/app/build.gradle @@ -28,7 +28,7 @@ if (flutterVersionName == null) { android { namespace 'com.baseflow.permissionhandler.example' - compileSdkVersion 35 + compileSdkVersion 37 defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). From 886cd981391ac0685e00c4da0ae748c0cdf378a5 Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 3 Jun 2026 13:02:41 +0200 Subject: [PATCH 24/57] update code coverage for permission_handler_platform_interface, add android 37 sdk --- .github/workflows/permission_handler.yaml | 5 ++++ .../workflows/permission_handler_android.yaml | 27 ++++++++++--------- ...permission_handler_platform_interface.yaml | 27 ++++++++++--------- 3 files changed, 34 insertions(+), 25 deletions(-) diff --git a/.github/workflows/permission_handler.yaml b/.github/workflows/permission_handler.yaml index 89a456d75..8b202d803 100644 --- a/.github/workflows/permission_handler.yaml +++ b/.github/workflows/permission_handler.yaml @@ -75,6 +75,11 @@ jobs: flags: unittests # optional name: permission_handler # optional + # Ensure that the android "platforms;android-37 is installed" + - name: Setup Android SDK + uses: android-actions/setup-android@v4 + with: + packages: "tools platform-tools platforms;android-37" # Build Android version of the example App - name: Run Android build run: flutter build apk --release diff --git a/.github/workflows/permission_handler_android.yaml b/.github/workflows/permission_handler_android.yaml index 0bbe16316..b7c403b1e 100644 --- a/.github/workflows/permission_handler_android.yaml +++ b/.github/workflows/permission_handler_android.yaml @@ -6,15 +6,15 @@ name: permission_handler_android # events but only for the main branch on: push: - branches: [ main ] + branches: [main] paths: - - 'permission_handler_android/**' - - '.github/workflows/permission_handler_android.yaml' + - "permission_handler_android/**" + - ".github/workflows/permission_handler_android.yaml" pull_request: - branches: [ main ] + branches: [main] paths: - - 'permission_handler_android/**' - - '.github/workflows/permission_handler_android.yaml' + - "permission_handler_android/**" + - ".github/workflows/permission_handler_android.yaml" # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: @@ -26,7 +26,7 @@ jobs: env: source-directory: ./permission_handler_android - example-directory: ./permission_handler_android/example + example-directory: ./permission_handler_android/example # Steps represent a sequence of tasks that will be executed as part of the job steps: @@ -36,13 +36,12 @@ jobs: # Make sure JAVA version 17 is installed on build agent. - uses: actions/setup-java@v3 with: - distribution: 'temurin' # See 'Supported distributions' for available options - java-version: '17' - + distribution: "temurin" # See 'Supported distributions' for available options + java-version: "17" # Make sure the stable version of Flutter is available - uses: subosito/flutter-action@v2 with: - channel: 'stable' + channel: "stable" # Download all Flutter packages - name: Download dependencies @@ -59,8 +58,12 @@ jobs: run: flutter analyze working-directory: ${{env.source-directory}} + # Ensure that the android "platforms;android-37 is installed" + - name: Setup Android SDK + uses: android-actions/setup-android@v4 + with: + packages: "tools platform-tools platforms;android-37" # Build Android version of the example App - name: Run Android build run: flutter build apk --release working-directory: ${{env.example-directory}} - \ No newline at end of file diff --git a/.github/workflows/permission_handler_platform_interface.yaml b/.github/workflows/permission_handler_platform_interface.yaml index 4f6408b78..46344a92b 100644 --- a/.github/workflows/permission_handler_platform_interface.yaml +++ b/.github/workflows/permission_handler_platform_interface.yaml @@ -6,15 +6,15 @@ name: permission_handler_platform_interface # events but only for the main branch on: push: - branches: [ main ] + branches: [main] paths: - - 'permission_handler_platform_interface/**' - - '.github/workflows/permission_handler_platform_interface.yaml' + - "permission_handler_platform_interface/**" + - ".github/workflows/permission_handler_platform_interface.yaml" pull_request: - branches: [ main ] + branches: [main] paths: - - 'permission_handler_platform_interface/**' - - '.github/workflows/permission_handler_platform_interface.yaml' + - "permission_handler_platform_interface/**" + - ".github/workflows/permission_handler_platform_interface.yaml" # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: @@ -25,17 +25,17 @@ jobs: runs-on: ubuntu-latest env: - source-directory: ./permission_handler_platform_interface + source-directory: ./permission_handler_platform_interface # Steps represent a sequence of tasks that will be executed as part of the job steps: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - uses: actions/checkout@v3 - + # Make sure the stable version of Flutter is available - uses: subosito/flutter-action@v2 with: - channel: 'stable' + channel: "stable" # Download all Flutter packages - name: Download dependencies @@ -46,20 +46,21 @@ jobs: - name: Run Dart Format run: dart format --set-exit-if-changed . working-directory: ${{env.source-directory}} - + # Run Flutter Analyzer - name: Run Flutter Analyzer run: flutter analyze working-directory: ${{env.source-directory}} - + # Run all unit-tests with code coverage - name: Run unit tests run: flutter test --coverage working-directory: ${{env.source-directory}} # Upload code coverage information - - uses: codecov/codecov-action@v1 + - uses: codecov/codecov-action@v3 with: + token: ${{ secrets.CODECOV_TOKEN }} file: ${{env.source-directory}}/coverage/lcov.info # optional name: permission_handler_platform_interface (Platform Interface Package) # optional - fail_ci_if_error: true \ No newline at end of file + flags: unittests From 2be9ae3a5efb75150b567aac30a4fe590f804673 Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 3 Jun 2026 13:07:26 +0200 Subject: [PATCH 25/57] ...it is android 37.0, not android 37 --- .github/workflows/permission_handler.yaml | 2 +- .github/workflows/permission_handler_android.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/permission_handler.yaml b/.github/workflows/permission_handler.yaml index 8b202d803..ce565c06c 100644 --- a/.github/workflows/permission_handler.yaml +++ b/.github/workflows/permission_handler.yaml @@ -79,7 +79,7 @@ jobs: - name: Setup Android SDK uses: android-actions/setup-android@v4 with: - packages: "tools platform-tools platforms;android-37" + packages: "tools platform-tools platforms;android-37.0" # Build Android version of the example App - name: Run Android build run: flutter build apk --release diff --git a/.github/workflows/permission_handler_android.yaml b/.github/workflows/permission_handler_android.yaml index b7c403b1e..1deaebd08 100644 --- a/.github/workflows/permission_handler_android.yaml +++ b/.github/workflows/permission_handler_android.yaml @@ -62,7 +62,7 @@ jobs: - name: Setup Android SDK uses: android-actions/setup-android@v4 with: - packages: "tools platform-tools platforms;android-37" + packages: "tools platform-tools platforms;android-37.0" # Build Android version of the example App - name: Run Android build run: flutter build apk --release From 84fbc3e3a884e2fb380a14ab8cc0e10489b8a911 Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 3 Jun 2026 13:20:06 +0200 Subject: [PATCH 26/57] try to symlink the android-37.0 directory to android-37? --- .github/workflows/permission_handler.yaml | 19 +++++++++++++------ .../workflows/permission_handler_android.yaml | 19 ++++++++++++++----- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/.github/workflows/permission_handler.yaml b/.github/workflows/permission_handler.yaml index ce565c06c..9379808ab 100644 --- a/.github/workflows/permission_handler.yaml +++ b/.github/workflows/permission_handler.yaml @@ -42,7 +42,19 @@ jobs: with: distribution: "temurin" # See 'Supported distributions' for available options java-version: "17" - + # Ensure that the android "platforms;android-37 is installed" + - name: Setup Android SDK + uses: android-actions/setup-android@v4 + with: + packages: "tools platform-tools platforms;android-37.0" + # Symlink the android-37.0 to android-37 + - name: Symlink android-37.0 to android-37 + run: | + if [ -d "$ANDROID_HOME/platforms/android-37.0" ]; then + ln -s "$ANDROID_HOME/platforms/android-37.0" "$ANDROID_HOME/platforms/android-37" + else + echo "android-37.0 not found, skipping symlink" + fi # Make sure the stable version of Flutter is available - uses: subosito/flutter-action@v2 with: @@ -75,11 +87,6 @@ jobs: flags: unittests # optional name: permission_handler # optional - # Ensure that the android "platforms;android-37 is installed" - - name: Setup Android SDK - uses: android-actions/setup-android@v4 - with: - packages: "tools platform-tools platforms;android-37.0" # Build Android version of the example App - name: Run Android build run: flutter build apk --release diff --git a/.github/workflows/permission_handler_android.yaml b/.github/workflows/permission_handler_android.yaml index 1deaebd08..6a19784cd 100644 --- a/.github/workflows/permission_handler_android.yaml +++ b/.github/workflows/permission_handler_android.yaml @@ -38,6 +38,20 @@ jobs: with: distribution: "temurin" # See 'Supported distributions' for available options java-version: "17" + + # Ensure that the android "platforms;android-37 is installed" + - name: Setup Android SDK + uses: android-actions/setup-android@v4 + with: + packages: "tools platform-tools platforms;android-37.0" + # Symlink the android-37.0 to android-37 + - name: Symlink android-37.0 to android-37 + run: | + if [ -d "$ANDROID_HOME/platforms/android-37.0" ]; then + ln -s "$ANDROID_HOME/platforms/android-37.0" "$ANDROID_HOME/platforms/android-37" + else + echo "android-37.0 not found, skipping symlink" + fi # Make sure the stable version of Flutter is available - uses: subosito/flutter-action@v2 with: @@ -58,11 +72,6 @@ jobs: run: flutter analyze working-directory: ${{env.source-directory}} - # Ensure that the android "platforms;android-37 is installed" - - name: Setup Android SDK - uses: android-actions/setup-android@v4 - with: - packages: "tools platform-tools platforms;android-37.0" # Build Android version of the example App - name: Run Android build run: flutter build apk --release From 3d6dfcd0f85a457c7ca3abec42ca8cc735417c7e Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 3 Jun 2026 13:28:59 +0200 Subject: [PATCH 27/57] ohhh...i think it is flutter. --- .github/workflows/permission_handler.yaml | 15 +-------------- .../workflows/permission_handler_android.yaml | 16 +--------------- 2 files changed, 2 insertions(+), 29 deletions(-) diff --git a/.github/workflows/permission_handler.yaml b/.github/workflows/permission_handler.yaml index 9379808ab..b5015bb98 100644 --- a/.github/workflows/permission_handler.yaml +++ b/.github/workflows/permission_handler.yaml @@ -42,23 +42,10 @@ jobs: with: distribution: "temurin" # See 'Supported distributions' for available options java-version: "17" - # Ensure that the android "platforms;android-37 is installed" - - name: Setup Android SDK - uses: android-actions/setup-android@v4 - with: - packages: "tools platform-tools platforms;android-37.0" - # Symlink the android-37.0 to android-37 - - name: Symlink android-37.0 to android-37 - run: | - if [ -d "$ANDROID_HOME/platforms/android-37.0" ]; then - ln -s "$ANDROID_HOME/platforms/android-37.0" "$ANDROID_HOME/platforms/android-37" - else - echo "android-37.0 not found, skipping symlink" - fi # Make sure the stable version of Flutter is available - uses: subosito/flutter-action@v2 with: - channel: "stable" + channel: "beta" # Download all Flutter packages - name: Download dependencies diff --git a/.github/workflows/permission_handler_android.yaml b/.github/workflows/permission_handler_android.yaml index 6a19784cd..03cd8923c 100644 --- a/.github/workflows/permission_handler_android.yaml +++ b/.github/workflows/permission_handler_android.yaml @@ -38,24 +38,10 @@ jobs: with: distribution: "temurin" # See 'Supported distributions' for available options java-version: "17" - - # Ensure that the android "platforms;android-37 is installed" - - name: Setup Android SDK - uses: android-actions/setup-android@v4 - with: - packages: "tools platform-tools platforms;android-37.0" - # Symlink the android-37.0 to android-37 - - name: Symlink android-37.0 to android-37 - run: | - if [ -d "$ANDROID_HOME/platforms/android-37.0" ]; then - ln -s "$ANDROID_HOME/platforms/android-37.0" "$ANDROID_HOME/platforms/android-37" - else - echo "android-37.0 not found, skipping symlink" - fi # Make sure the stable version of Flutter is available - uses: subosito/flutter-action@v2 with: - channel: "stable" + channel: "beta" # Download all Flutter packages - name: Download dependencies From 0bbd3907e3476cb2c11e7045409d74fc53a8ffaf Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 3 Jun 2026 14:20:56 +0200 Subject: [PATCH 28/57] yes, flutter, but also outdated kotlin / gradle, etc --- .github/workflows/permission_handler.yaml | 2 +- .../workflows/permission_handler_android.yaml | 2 +- .../example/android/app/build.gradle | 55 ----------------- .../example/android/app/build.gradle.kts | 45 ++++++++++++++ .../example/android/build.gradle | 18 ------ .../example/android/build.gradle.kts | 24 ++++++++ .../example/android/gradle.properties | 7 ++- .../gradle/wrapper/gradle-wrapper.properties | 2 +- .../example/android/settings.gradle | 24 -------- .../example/android/settings.gradle.kts | 26 ++++++++ .../example/android/app/build.gradle | 60 ++++++++----------- .../example/android/build.gradle | 30 ---------- .../example/android/build.gradle.kts | 24 ++++++++ .../example/android/gradle.properties | 7 ++- .../gradle/wrapper/gradle-wrapper.properties | 5 +- .../example/android/settings.gradle | 24 -------- .../example/android/settings.gradle.kts | 26 ++++++++ 17 files changed, 187 insertions(+), 194 deletions(-) delete mode 100644 permission_handler/example/android/app/build.gradle create mode 100644 permission_handler/example/android/app/build.gradle.kts delete mode 100644 permission_handler/example/android/build.gradle create mode 100644 permission_handler/example/android/build.gradle.kts delete mode 100644 permission_handler/example/android/settings.gradle create mode 100644 permission_handler/example/android/settings.gradle.kts delete mode 100644 permission_handler_android/example/android/build.gradle create mode 100644 permission_handler_android/example/android/build.gradle.kts delete mode 100644 permission_handler_android/example/android/settings.gradle create mode 100644 permission_handler_android/example/android/settings.gradle.kts diff --git a/.github/workflows/permission_handler.yaml b/.github/workflows/permission_handler.yaml index b5015bb98..99f138b23 100644 --- a/.github/workflows/permission_handler.yaml +++ b/.github/workflows/permission_handler.yaml @@ -45,7 +45,7 @@ jobs: # Make sure the stable version of Flutter is available - uses: subosito/flutter-action@v2 with: - channel: "beta" + channel: "stable" # Download all Flutter packages - name: Download dependencies diff --git a/.github/workflows/permission_handler_android.yaml b/.github/workflows/permission_handler_android.yaml index 03cd8923c..547ff265f 100644 --- a/.github/workflows/permission_handler_android.yaml +++ b/.github/workflows/permission_handler_android.yaml @@ -41,7 +41,7 @@ jobs: # Make sure the stable version of Flutter is available - uses: subosito/flutter-action@v2 with: - channel: "beta" + channel: "stable" # Download all Flutter packages - name: Download dependencies diff --git a/permission_handler/example/android/app/build.gradle b/permission_handler/example/android/app/build.gradle deleted file mode 100644 index 25715f826..000000000 --- a/permission_handler/example/android/app/build.gradle +++ /dev/null @@ -1,55 +0,0 @@ -plugins { - id "com.android.application" - id "dev.flutter.flutter-gradle-plugin" -} - -def localProperties = new Properties() -def localPropertiesFile = rootProject.file('local.properties') -if (localPropertiesFile.exists()) { - localPropertiesFile.withReader('UTF-8') { reader -> - localProperties.load(reader) - } -} - -def flutterVersionCode = localProperties.getProperty('flutter.versionCode') -if (flutterVersionCode == null) { - flutterVersionCode = '1' -} - -def flutterVersionName = localProperties.getProperty('flutter.versionName') -if (flutterVersionName == null) { - flutterVersionName = '1.0' -} - -android { - if (project.android.hasProperty("namespace")) { - namespace 'com.baseflow.permissionhandlerexample' - } - compileSdkVersion 37 - - compileOptions { - sourceCompatibility JavaVersion.VERSION_17 - targetCompatibility JavaVersion.VERSION_17 - } - - defaultConfig { - // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId "com.baseflow.permissionhandler.example" - minSdkVersion flutter.minSdkVersion - targetSdkVersion 34 - versionCode flutterVersionCode.toInteger() - versionName flutterVersionName - } - - buildTypes { - release { - // TODO: Add your own signing config for the release build. - // Signing with the debug keys for now, so `flutter run --release` works. - signingConfig signingConfigs.debug - } - } -} - -flutter { - source '../..' -} diff --git a/permission_handler/example/android/app/build.gradle.kts b/permission_handler/example/android/app/build.gradle.kts new file mode 100644 index 000000000..602003d43 --- /dev/null +++ b/permission_handler/example/android/app/build.gradle.kts @@ -0,0 +1,45 @@ +plugins { + id("com.android.application") + // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. + id("dev.flutter.flutter-gradle-plugin") +} + +android { + namespace = "com.baseflow.permissionhandler.example" + compileSdk = 37 + ndkVersion = flutter.ndkVersion + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId = "com.baseflow.permissionhandler.example" + // You can update the following values to match your application needs. + // For more information, see: https://flutter.dev/to/review-gradle-config. + minSdk = flutter.minSdkVersion + targetSdk = 35 + versionCode = flutter.versionCode + versionName = flutter.versionName + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig = signingConfigs.getByName("debug") + } + } +} + +kotlin { + compilerOptions { + jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 + } +} + +flutter { + source = "../.." +} diff --git a/permission_handler/example/android/build.gradle b/permission_handler/example/android/build.gradle deleted file mode 100644 index 8f31e8caf..000000000 --- a/permission_handler/example/android/build.gradle +++ /dev/null @@ -1,18 +0,0 @@ -allprojects { - repositories { - google() - mavenCentral() - } -} - -rootProject.buildDir = '../build' -subprojects { - project.buildDir = "${rootProject.buildDir}/${project.name}" -} -subprojects { - project.evaluationDependsOn(':app') -} - -tasks.register("clean", Delete) { - delete rootProject.buildDir -} \ No newline at end of file diff --git a/permission_handler/example/android/build.gradle.kts b/permission_handler/example/android/build.gradle.kts new file mode 100644 index 000000000..dbee657bb --- /dev/null +++ b/permission_handler/example/android/build.gradle.kts @@ -0,0 +1,24 @@ +allprojects { + repositories { + google() + mavenCentral() + } +} + +val newBuildDir: Directory = + rootProject.layout.buildDirectory + .dir("../../build") + .get() +rootProject.layout.buildDirectory.value(newBuildDir) + +subprojects { + val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name) + project.layout.buildDirectory.value(newSubprojectBuildDir) +} +subprojects { + project.evaluationDependsOn(":app") +} + +tasks.register("clean") { + delete(rootProject.layout.buildDirectory) +} diff --git a/permission_handler/example/android/gradle.properties b/permission_handler/example/android/gradle.properties index 94adc3a3f..d5da7278a 100644 --- a/permission_handler/example/android/gradle.properties +++ b/permission_handler/example/android/gradle.properties @@ -1,3 +1,6 @@ -org.gradle.jvmargs=-Xmx1536M +org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError android.useAndroidX=true -android.enableJetifier=true +# This builtInKotlin flag was added automatically by Flutter migrator +android.builtInKotlin=false +# This newDsl flag was added automatically by Flutter migrator +android.newDsl=false diff --git a/permission_handler/example/android/gradle/wrapper/gradle-wrapper.properties b/permission_handler/example/android/gradle/wrapper/gradle-wrapper.properties index 9162f1008..a97e89ca1 100644 --- a/permission_handler/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/permission_handler/example/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-all.zip diff --git a/permission_handler/example/android/settings.gradle b/permission_handler/example/android/settings.gradle deleted file mode 100644 index 8cbe490f3..000000000 --- a/permission_handler/example/android/settings.gradle +++ /dev/null @@ -1,24 +0,0 @@ -pluginManagement { - def flutterSdkPath = { - def properties = new Properties() - file("local.properties").withInputStream { properties.load(it) } - def flutterSdkPath = properties.getProperty("flutter.sdk") - assert flutterSdkPath != null, "flutter.sdk not set in local.properties" - return flutterSdkPath - }() - - includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") - - repositories { - google() - mavenCentral() - gradlePluginPortal() - } -} - -plugins { - id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "8.9.1" apply false -} - -include ":app" \ No newline at end of file diff --git a/permission_handler/example/android/settings.gradle.kts b/permission_handler/example/android/settings.gradle.kts new file mode 100644 index 000000000..c21f0c5b4 --- /dev/null +++ b/permission_handler/example/android/settings.gradle.kts @@ -0,0 +1,26 @@ +pluginManagement { + val flutterSdkPath = + run { + val properties = java.util.Properties() + file("local.properties").inputStream().use { properties.load(it) } + val flutterSdkPath = properties.getProperty("flutter.sdk") + require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" } + flutterSdkPath + } + + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") + + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} + +plugins { + id("dev.flutter.flutter-plugin-loader") version "1.0.0" + id("com.android.application") version "9.0.1" apply false + id("org.jetbrains.kotlin.android") version "2.3.20" apply false +} + +include(":app") diff --git a/permission_handler_android/example/android/app/build.gradle b/permission_handler_android/example/android/app/build.gradle index d740562c6..602003d43 100644 --- a/permission_handler_android/example/android/app/build.gradle +++ b/permission_handler_android/example/android/app/build.gradle @@ -1,53 +1,45 @@ plugins { - id "com.android.application" - id "dev.flutter.flutter-gradle-plugin" -} - -def localProperties = new Properties() -def localPropertiesFile = rootProject.file('local.properties') -if (localPropertiesFile.exists()) { - localPropertiesFile.withReader('UTF-8') { reader -> - localProperties.load(reader) - } -} - -def flutterRoot = localProperties.getProperty('flutter.sdk') -if (flutterRoot == null) { - throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") -} - -def flutterVersionCode = localProperties.getProperty('flutter.versionCode') -if (flutterVersionCode == null) { - flutterVersionCode = '1' -} - -def flutterVersionName = localProperties.getProperty('flutter.versionName') -if (flutterVersionName == null) { - flutterVersionName = '1.0' + id("com.android.application") + // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. + id("dev.flutter.flutter-gradle-plugin") } android { - namespace 'com.baseflow.permissionhandler.example' - compileSdkVersion 37 + namespace = "com.baseflow.permissionhandler.example" + compileSdk = 37 + ndkVersion = flutter.ndkVersion + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId "com.baseflow.permissionhandler.example" - minSdkVersion flutter.minSdkVersion - targetSdkVersion 35 - versionCode flutterVersionCode.toInteger() - versionName flutterVersionName + applicationId = "com.baseflow.permissionhandler.example" + // You can update the following values to match your application needs. + // For more information, see: https://flutter.dev/to/review-gradle-config. + minSdk = flutter.minSdkVersion + targetSdk = 35 + versionCode = flutter.versionCode + versionName = flutter.versionName } buildTypes { release { // TODO: Add your own signing config for the release build. // Signing with the debug keys for now, so `flutter run --release` works. - signingConfig signingConfigs.debug + signingConfig = signingConfigs.getByName("debug") } } } +kotlin { + compilerOptions { + jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 + } +} + flutter { - source '../..' + source = "../.." } diff --git a/permission_handler_android/example/android/build.gradle b/permission_handler_android/example/android/build.gradle deleted file mode 100644 index 0ed2bee85..000000000 --- a/permission_handler_android/example/android/build.gradle +++ /dev/null @@ -1,30 +0,0 @@ -allprojects { - repositories { - google() - mavenCentral() - } -} - -rootProject.buildDir = '../build' -subprojects { - project.buildDir = "${rootProject.buildDir}/${project.name}" -} -subprojects { - project.evaluationDependsOn(':app') -} - -tasks.register("clean", Delete) { - delete rootProject.buildDir -} - -// Build the plugin project with warnings enabled. This is here rather than -// in the plugin itself to avoid breaking clients that have different -// warnings (e.g., deprecation warnings from a newer SDK than this project -// builds with). -gradle.projectsEvaluated { - project(":permission_handler_android") { - tasks.withType(JavaCompile) { - options.compilerArgs << "-Xlint:all" << "-Werror" - } - } -} diff --git a/permission_handler_android/example/android/build.gradle.kts b/permission_handler_android/example/android/build.gradle.kts new file mode 100644 index 000000000..dbee657bb --- /dev/null +++ b/permission_handler_android/example/android/build.gradle.kts @@ -0,0 +1,24 @@ +allprojects { + repositories { + google() + mavenCentral() + } +} + +val newBuildDir: Directory = + rootProject.layout.buildDirectory + .dir("../../build") + .get() +rootProject.layout.buildDirectory.value(newBuildDir) + +subprojects { + val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name) + project.layout.buildDirectory.value(newSubprojectBuildDir) +} +subprojects { + project.evaluationDependsOn(":app") +} + +tasks.register("clean") { + delete(rootProject.layout.buildDirectory) +} diff --git a/permission_handler_android/example/android/gradle.properties b/permission_handler_android/example/android/gradle.properties index 598d13fee..d5da7278a 100644 --- a/permission_handler_android/example/android/gradle.properties +++ b/permission_handler_android/example/android/gradle.properties @@ -1,3 +1,6 @@ -org.gradle.jvmargs=-Xmx4G +org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError android.useAndroidX=true -android.enableJetifier=true +# This builtInKotlin flag was added automatically by Flutter migrator +android.builtInKotlin=false +# This newDsl flag was added automatically by Flutter migrator +android.newDsl=false diff --git a/permission_handler_android/example/android/gradle/wrapper/gradle-wrapper.properties b/permission_handler_android/example/android/gradle/wrapper/gradle-wrapper.properties index db18181ac..2e1113280 100644 --- a/permission_handler_android/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/permission_handler_android/example/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ -#Fri Jun 23 08:50:38 CEST 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip +networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip diff --git a/permission_handler_android/example/android/settings.gradle b/permission_handler_android/example/android/settings.gradle deleted file mode 100644 index 56eb85cb1..000000000 --- a/permission_handler_android/example/android/settings.gradle +++ /dev/null @@ -1,24 +0,0 @@ -pluginManagement { - def flutterSdkPath = { - def properties = new Properties() - file("local.properties").withInputStream { properties.load(it) } - def flutterSdkPath = properties.getProperty("flutter.sdk") - assert flutterSdkPath != null, "flutter.sdk not set in local.properties" - return flutterSdkPath - }() - - includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") - - repositories { - google() - mavenCentral() - gradlePluginPortal() - } -} - -plugins { - id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "8.7.0" apply false -} - -include ":app" \ No newline at end of file diff --git a/permission_handler_android/example/android/settings.gradle.kts b/permission_handler_android/example/android/settings.gradle.kts new file mode 100644 index 000000000..c21f0c5b4 --- /dev/null +++ b/permission_handler_android/example/android/settings.gradle.kts @@ -0,0 +1,26 @@ +pluginManagement { + val flutterSdkPath = + run { + val properties = java.util.Properties() + file("local.properties").inputStream().use { properties.load(it) } + val flutterSdkPath = properties.getProperty("flutter.sdk") + require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" } + flutterSdkPath + } + + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") + + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} + +plugins { + id("dev.flutter.flutter-plugin-loader") version "1.0.0" + id("com.android.application") version "9.0.1" apply false + id("org.jetbrains.kotlin.android") version "2.3.20" apply false +} + +include(":app") From 97418fd6f30a74d5a5c02b8bbf92d9bfcb26c37b Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 3 Jun 2026 14:39:30 +0200 Subject: [PATCH 29/57] feat(apple): add Swift Package Manager support (#1523) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(apple): create SPM source directory structure * feat(apple): move ObjC sources to SPM-compatible structure * feat(apple): add public header for SPM plugin registration * feat(apple): move PrivacyInfo.xcprivacy to SPM sources * feat(apple): add Package.swift for Swift Package Manager support * feat(apple): update podspec to reference SPM source structure * chore(apple): ignore SPM build artifacts * docs: add SPM setup instructions to README * fix(apple): move Package.swift to correct SPM location (ios/permission_handler_apple/) * fix(apple): add missing PERMISSION_PHOTOS_ADD_ONLY and PERMISSION_LOCATION_ALWAYS defines * fix(apple): use forward declaration in public header to avoid missing internal import * fix(example): bump compileSdk to 36, AGP to 8.9.1, Gradle to 8.11.1 * fix(apple): add explicit UIKit import to strategies that use UIApplication under SPM * feat(apple): auto-detect permissions from Info.plist in Package.swift Package.swift now walks up the directory tree from its own location to find the app's Info.plist and enables each permission define when the corresponding usage description key is present. This mirrors the CocoaPods workflow: adding NSCameraUsageDescription to Info.plist is all that is needed to activate PERMISSION_CAMERA, with no extra configuration files or terminal commands. Environment variables remain supported as an explicit override (priority over Info.plist), which covers PermissionGroup.notification and criticalAlerts that have no required Info.plist key. Users must clear DerivedData once after changing Info.plist so Xcode re-evaluates the manifest: rm -rf ~/Library/Developer/Xcode/DerivedData * docs: update SPM setup instructions to use Info.plist auto-detection Replace the launchctl setenv / pre-action script approach with the new Info.plist-based mechanism: permissions are now enabled automatically when the corresponding usage description key is present in Info.plist, which is already required for any permission to work at runtime. Document the two permissions without an Info.plist key (notification, criticalAlerts) as the only case still requiring an env var. * chore(example): update iOS example app and remove plan artifact - Add all permission usage description keys to Info.plist so the SPM Info.plist auto-detection covers all permissions out of the box - Comment out the Siri entitlement (requires a paid Apple Developer account; uncomment to test PERMISSION_ASSISTANT) - Update AppDelegate to modern FlutterImplicitEngineDelegate pattern - Bump Podfile iOS platform to 13.0 - Remove docs/superpowers/plans/2026-05-05-spm-support.md (internal planning artifact not intended for the public repo) * chore(apple): bump version to 9.4.8 and update CHANGELOG * fix(apple): correct SPM permission flag mapping for photos and calendarWriteOnly - PERMISSION_PHOTOS now triggers on NSPhotoLibraryAddUsageDescription alone, since PhotoPermissionStrategy (which handles photosAddOnly) compiles under PERMISSION_PHOTOS — without this, photosAddOnly silently fell back to UnknownPermissionStrategy when NSPhotoLibraryUsageDescription was absent - PERMISSION_EVENTS_FULL_ACCESS now also triggers on NSCalendarsWriteOnlyAccessUsageDescription (iOS 17+), enabling calendarWriteOnly which requires PERMISSION_EVENTS || PERMISSION_EVENTS_FULL_ACCESS in native code - Sync podspec version to 9.4.8 - Restore NSCameraUsageDescription in example Info.plist (lost during rewrite) - Add NSCalendarsWriteOnlyAccessUsageDescription to example Info.plist * docs: add calendarWriteOnly to SPM permission table in README * fix(example): remove NSSiriUsageDescription and document permission constraints Siri requires the com.apple.developer.siri entitlement; including NSSiriUsageDescription without it crashes the app on launch under SPM. Added a README section listing permissions that cannot be tested on simulator or without special entitlements. * fix(apple): enable notifications and criticalAlerts by default under SPM These permissions have no required Info.plist key so the previous logic always compiled them out (defaultValue "0"), causing permanentlyDenied to be returned without ever showing a system dialog. They are now enabled by default and can be opted out via env var set to "0". * fix(apple): revert criticalAlerts to opt-in under SPM criticalAlerts requires a special Apple entitlement; compiling it into every app by default would add dead code for apps that don't use it. Only PERMISSION_NOTIFICATIONS defaults to enabled (no entitlement needed). * docs: clarify SPM special cases for notification and criticalAlerts - Add both permissions to the Info.plist table with notes - Distinguish export (terminal) vs launchctl setenv (Xcode GUI) - Explain why criticalAlerts is opt-in (Apple entitlement required) * chore(example): enable SPM in Xcode project for iOS example app Flutter auto-generated FlutterGeneratedPluginSwiftPackage reference when running with --enable-swift-package-manager. * fix(example): align Java source/target compatibility to VERSION_17 AGP 8.x + Kotlin 1.9+ enforce JVM-target consistency; compileJava was still on 1.8 while compileKotlin used 17, causing the build to fail. --- permission_handler/README.md | 63 +++++++ .../example/android/app/build.gradle | 6 +- .../gradle/wrapper/gradle-wrapper.properties | 2 +- .../example/android/settings.gradle | 2 +- permission_handler_apple/CHANGELOG.md | 8 +- permission_handler_apple/example/README.md | 11 ++ .../ios/Flutter/AppFrameworkInfo.plist | 2 - .../Package.swift | 32 ++++ .../FlutterGeneratedPluginSwiftPackage.swift | 3 + .../Flutter/ephemeral/flutter_lldb_helper.py | 32 ++++ .../ios/Flutter/ephemeral/flutter_lldbinit | 5 + .../ephemeral/flutter_native_integration.env | 12 ++ permission_handler_apple/example/ios/Podfile | 2 +- .../ios/Runner.xcodeproj/project.pbxproj | 66 +++----- .../xcshareddata/xcschemes/Runner.xcscheme | 31 +++- .../example/ios/Runner/AppDelegate.swift | 11 +- .../example/ios/Runner/Info.plist | 134 ++++++++------- .../ios/Runner/RunnerDebug.entitlements | 3 + permission_handler_apple/ios/.gitignore | 4 + .../ios/permission_handler_apple.podspec | 10 +- .../permission_handler_apple/Package.swift | 156 ++++++++++++++++++ .../PermissionHandlerEnums.h | 0 .../PermissionHandlerPlugin.h | 0 .../PermissionHandlerPlugin.m | 0 .../PermissionManager.h | 0 .../PermissionManager.m | 0 .../PrivacyInfo.xcprivacy | 0 .../PermissionHandlerPlugin.h | 7 + ...ppTrackingTransparencyPermissionStrategy.h | 0 ...ppTrackingTransparencyPermissionStrategy.m | 0 .../strategies/AssistantPermissionStrategy.h | 0 .../strategies/AssistantPermissionStrategy.m | 0 .../strategies/AudioVideoPermissionStrategy.h | 0 .../strategies/AudioVideoPermissionStrategy.m | 0 .../strategies/BackgroundRefreshStrategy.h | 1 + .../strategies/BackgroundRefreshStrategy.m | 0 .../strategies/BluetoothPermissionStrategy.h | 0 .../strategies/BluetoothPermissionStrategy.m | 0 .../strategies/ContactPermissionStrategy.h | 0 .../strategies/ContactPermissionStrategy.m | 0 .../CriticalAlertsPermissionStrategy.h | 1 + .../CriticalAlertsPermissionStrategy.m | 0 .../strategies/EventPermissionStrategy.h | 0 .../strategies/EventPermissionStrategy.m | 0 .../strategies/LocationPermissionStrategy.h | 1 + .../strategies/LocationPermissionStrategy.m | 0 .../MediaLibraryPermissionStrategy.h | 0 .../MediaLibraryPermissionStrategy.m | 0 .../NotificationPermissionStrategy.h | 1 + .../NotificationPermissionStrategy.m | 0 .../strategies/PermissionStrategy.h | 0 .../strategies/PhonePermissionStrategy.h | 1 + .../strategies/PhonePermissionStrategy.m | 0 .../strategies/PhotoPermissionStrategy.h | 0 .../strategies/PhotoPermissionStrategy.m | 0 .../strategies/SensorPermissionStrategy.h | 0 .../strategies/SensorPermissionStrategy.m | 0 .../strategies/SpeechPermissionStrategy.h | 0 .../strategies/SpeechPermissionStrategy.m | 0 .../strategies/StoragePermissionStrategy.h | 0 .../strategies/StoragePermissionStrategy.m | 0 .../strategies/UnknownPermissionStrategy.h | 0 .../strategies/UnknownPermissionStrategy.m | 0 .../permission_handler_apple}/util/Codec.h | 0 .../permission_handler_apple}/util/Codec.m | 0 65 files changed, 474 insertions(+), 133 deletions(-) create mode 100644 permission_handler_apple/example/ios/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage/Package.swift create mode 100644 permission_handler_apple/example/ios/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage/Sources/FlutterGeneratedPluginSwiftPackage/FlutterGeneratedPluginSwiftPackage.swift create mode 100644 permission_handler_apple/example/ios/Flutter/ephemeral/flutter_lldb_helper.py create mode 100644 permission_handler_apple/example/ios/Flutter/ephemeral/flutter_lldbinit create mode 100644 permission_handler_apple/example/ios/Flutter/ephemeral/flutter_native_integration.env create mode 100644 permission_handler_apple/ios/permission_handler_apple/Package.swift rename permission_handler_apple/ios/{Classes => permission_handler_apple/Sources/permission_handler_apple}/PermissionHandlerEnums.h (100%) rename permission_handler_apple/ios/{Classes => permission_handler_apple/Sources/permission_handler_apple}/PermissionHandlerPlugin.h (100%) rename permission_handler_apple/ios/{Classes => permission_handler_apple/Sources/permission_handler_apple}/PermissionHandlerPlugin.m (100%) rename permission_handler_apple/ios/{Classes => permission_handler_apple/Sources/permission_handler_apple}/PermissionManager.h (100%) rename permission_handler_apple/ios/{Classes => permission_handler_apple/Sources/permission_handler_apple}/PermissionManager.m (100%) rename permission_handler_apple/ios/{Resources => permission_handler_apple/Sources/permission_handler_apple}/PrivacyInfo.xcprivacy (100%) create mode 100644 permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/include/permission_handler_apple/PermissionHandlerPlugin.h rename permission_handler_apple/ios/{Classes => permission_handler_apple/Sources/permission_handler_apple}/strategies/AppTrackingTransparencyPermissionStrategy.h (100%) rename permission_handler_apple/ios/{Classes => permission_handler_apple/Sources/permission_handler_apple}/strategies/AppTrackingTransparencyPermissionStrategy.m (100%) rename permission_handler_apple/ios/{Classes => permission_handler_apple/Sources/permission_handler_apple}/strategies/AssistantPermissionStrategy.h (100%) rename permission_handler_apple/ios/{Classes => permission_handler_apple/Sources/permission_handler_apple}/strategies/AssistantPermissionStrategy.m (100%) rename permission_handler_apple/ios/{Classes => permission_handler_apple/Sources/permission_handler_apple}/strategies/AudioVideoPermissionStrategy.h (100%) rename permission_handler_apple/ios/{Classes => permission_handler_apple/Sources/permission_handler_apple}/strategies/AudioVideoPermissionStrategy.m (100%) rename permission_handler_apple/ios/{Classes => permission_handler_apple/Sources/permission_handler_apple}/strategies/BackgroundRefreshStrategy.h (92%) rename permission_handler_apple/ios/{Classes => permission_handler_apple/Sources/permission_handler_apple}/strategies/BackgroundRefreshStrategy.m (100%) rename permission_handler_apple/ios/{Classes => permission_handler_apple/Sources/permission_handler_apple}/strategies/BluetoothPermissionStrategy.h (100%) rename permission_handler_apple/ios/{Classes => permission_handler_apple/Sources/permission_handler_apple}/strategies/BluetoothPermissionStrategy.m (100%) rename permission_handler_apple/ios/{Classes => permission_handler_apple/Sources/permission_handler_apple}/strategies/ContactPermissionStrategy.h (100%) rename permission_handler_apple/ios/{Classes => permission_handler_apple/Sources/permission_handler_apple}/strategies/ContactPermissionStrategy.m (100%) rename permission_handler_apple/ios/{Classes => permission_handler_apple/Sources/permission_handler_apple}/strategies/CriticalAlertsPermissionStrategy.h (95%) rename permission_handler_apple/ios/{Classes => permission_handler_apple/Sources/permission_handler_apple}/strategies/CriticalAlertsPermissionStrategy.m (100%) rename permission_handler_apple/ios/{Classes => permission_handler_apple/Sources/permission_handler_apple}/strategies/EventPermissionStrategy.h (100%) rename permission_handler_apple/ios/{Classes => permission_handler_apple/Sources/permission_handler_apple}/strategies/EventPermissionStrategy.m (100%) rename permission_handler_apple/ios/{Classes => permission_handler_apple/Sources/permission_handler_apple}/strategies/LocationPermissionStrategy.h (96%) rename permission_handler_apple/ios/{Classes => permission_handler_apple/Sources/permission_handler_apple}/strategies/LocationPermissionStrategy.m (100%) rename permission_handler_apple/ios/{Classes => permission_handler_apple/Sources/permission_handler_apple}/strategies/MediaLibraryPermissionStrategy.h (100%) rename permission_handler_apple/ios/{Classes => permission_handler_apple/Sources/permission_handler_apple}/strategies/MediaLibraryPermissionStrategy.m (100%) rename permission_handler_apple/ios/{Classes => permission_handler_apple/Sources/permission_handler_apple}/strategies/NotificationPermissionStrategy.h (95%) rename permission_handler_apple/ios/{Classes => permission_handler_apple/Sources/permission_handler_apple}/strategies/NotificationPermissionStrategy.m (100%) rename permission_handler_apple/ios/{Classes => permission_handler_apple/Sources/permission_handler_apple}/strategies/PermissionStrategy.h (100%) rename permission_handler_apple/ios/{Classes => permission_handler_apple/Sources/permission_handler_apple}/strategies/PhonePermissionStrategy.h (92%) rename permission_handler_apple/ios/{Classes => permission_handler_apple/Sources/permission_handler_apple}/strategies/PhonePermissionStrategy.m (100%) rename permission_handler_apple/ios/{Classes => permission_handler_apple/Sources/permission_handler_apple}/strategies/PhotoPermissionStrategy.h (100%) rename permission_handler_apple/ios/{Classes => permission_handler_apple/Sources/permission_handler_apple}/strategies/PhotoPermissionStrategy.m (100%) rename permission_handler_apple/ios/{Classes => permission_handler_apple/Sources/permission_handler_apple}/strategies/SensorPermissionStrategy.h (100%) rename permission_handler_apple/ios/{Classes => permission_handler_apple/Sources/permission_handler_apple}/strategies/SensorPermissionStrategy.m (100%) rename permission_handler_apple/ios/{Classes => permission_handler_apple/Sources/permission_handler_apple}/strategies/SpeechPermissionStrategy.h (100%) rename permission_handler_apple/ios/{Classes => permission_handler_apple/Sources/permission_handler_apple}/strategies/SpeechPermissionStrategy.m (100%) rename permission_handler_apple/ios/{Classes => permission_handler_apple/Sources/permission_handler_apple}/strategies/StoragePermissionStrategy.h (100%) rename permission_handler_apple/ios/{Classes => permission_handler_apple/Sources/permission_handler_apple}/strategies/StoragePermissionStrategy.m (100%) rename permission_handler_apple/ios/{Classes => permission_handler_apple/Sources/permission_handler_apple}/strategies/UnknownPermissionStrategy.h (100%) rename permission_handler_apple/ios/{Classes => permission_handler_apple/Sources/permission_handler_apple}/strategies/UnknownPermissionStrategy.m (100%) rename permission_handler_apple/ios/{Classes => permission_handler_apple/Sources/permission_handler_apple}/util/Codec.h (100%) rename permission_handler_apple/ios/{Classes => permission_handler_apple/Sources/permission_handler_apple}/util/Codec.m (100%) diff --git a/permission_handler/README.md b/permission_handler/README.md index 836bd1339..3e17adf3e 100644 --- a/permission_handler/README.md +++ b/permission_handler/README.md @@ -174,6 +174,69 @@ You must list the permission you want to use in your application: +
+Swift Package Manager (SPM) + +> Requires Flutter 3.24.0 or higher and Xcode 15.0 or higher. + +With SPM, `Package.swift` automatically detects which permissions to enable by reading your app's `Info.plist`. A permission is compiled in when its corresponding usage description key is present: + +| Permission group | Info.plist key | +|---|---| +| `PermissionGroup.calendar` (< iOS 17) | `NSCalendarsUsageDescription` | +| `PermissionGroup.calendarWriteOnly` (iOS 17+) | `NSCalendarsWriteOnlyAccessUsageDescription` | +| `PermissionGroup.calendarFullAccess` (iOS 17+) | `NSCalendarsFullAccessUsageDescription` | +| `PermissionGroup.reminders` | `NSRemindersUsageDescription` | +| `PermissionGroup.contacts` | `NSContactsUsageDescription` | +| `PermissionGroup.camera` | `NSCameraUsageDescription` | +| `PermissionGroup.microphone` | `NSMicrophoneUsageDescription` | +| `PermissionGroup.speech` | `NSSpeechRecognitionUsageDescription` | +| `PermissionGroup.photos` | `NSPhotoLibraryUsageDescription` | +| `PermissionGroup.photosAddOnly` | `NSPhotoLibraryAddUsageDescription` | +| `PermissionGroup.location` / `locationWhenInUse` | `NSLocationWhenInUseUsageDescription` | +| `PermissionGroup.locationAlways` | `NSLocationAlwaysAndWhenInUseUsageDescription` | +| `PermissionGroup.mediaLibrary` | `NSAppleMusicUsageDescription` | +| `PermissionGroup.sensors` | `NSMotionUsageDescription` | +| `PermissionGroup.bluetooth` | `NSBluetoothAlwaysUsageDescription` | +| `PermissionGroup.appTrackingTransparency` | `NSUserTrackingUsageDescription` | +| `PermissionGroup.assistant` | `NSSiriUsageDescription` | +| `PermissionGroup.notification` | *(enabled by default — see below)* | +| `PermissionGroup.criticalAlerts` | *(disabled by default — see below)* | + +Because you must already add these keys to `Info.plist` for any permission to work, no additional configuration file is needed. + +#### Special cases: permissions without an Info.plist key + +**`PermissionGroup.notification`** has no required `Info.plist` key and is **enabled by default**. To opt out, disable it via environment variable before building: + +```bash +# When building from terminal (flutter run / flutter build) +export PERMISSION_NOTIFICATIONS=0 + +# When building from Xcode GUI (set once per Mac session, then restart Xcode) +launchctl setenv PERMISSION_NOTIFICATIONS 0 +``` + +**`PermissionGroup.criticalAlerts`** requires a [special entitlement](https://developer.apple.com/documentation/usernotifications/asking-permission-to-use-notifications) granted by Apple and is **disabled by default** to avoid compiling unused code into apps that don't need it. Enable it explicitly: + +```bash +# When building from terminal +export PERMISSION_CRITICAL_ALERTS=1 + +# When building from Xcode GUI +launchctl setenv PERMISSION_CRITICAL_ALERTS 1 +``` + +**After changing any env var or Info.plist key**, clear Xcode's package cache once so `Package.swift` is re-evaluated: + +```bash +rm -rf ~/Library/Developer/Xcode/DerivedData +``` + +Then run `flutter build ios` or rebuild in Xcode as usual. + +
+ ## How to use There are a number of [`Permission`](https://pub.dev/documentation/permission_handler_platform_interface/latest/permission_handler_platform_interface/Permission-class.html#constants)s. diff --git a/permission_handler/example/android/app/build.gradle b/permission_handler/example/android/app/build.gradle index 537b42534..047e56a5c 100644 --- a/permission_handler/example/android/app/build.gradle +++ b/permission_handler/example/android/app/build.gradle @@ -25,11 +25,11 @@ android { if (project.android.hasProperty("namespace")) { namespace 'com.baseflow.permissionhandlerexample' } - compileSdkVersion 35 + compileSdkVersion 36 compileOptions { - sourceCompatibility JavaVersion.VERSION_1_8 - targetCompatibility JavaVersion.VERSION_1_8 + sourceCompatibility JavaVersion.VERSION_17 + targetCompatibility JavaVersion.VERSION_17 } defaultConfig { diff --git a/permission_handler/example/android/gradle/wrapper/gradle-wrapper.properties b/permission_handler/example/android/gradle/wrapper/gradle-wrapper.properties index db18181ac..9162f1008 100644 --- a/permission_handler/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/permission_handler/example/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-all.zip diff --git a/permission_handler/example/android/settings.gradle b/permission_handler/example/android/settings.gradle index 56eb85cb1..8cbe490f3 100644 --- a/permission_handler/example/android/settings.gradle +++ b/permission_handler/example/android/settings.gradle @@ -18,7 +18,7 @@ pluginManagement { plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "8.7.0" apply false + id "com.android.application" version "8.9.1" apply false } include ":app" \ No newline at end of file diff --git a/permission_handler_apple/CHANGELOG.md b/permission_handler_apple/CHANGELOG.md index 7f55591b5..05a0f3485 100644 --- a/permission_handler_apple/CHANGELOG.md +++ b/permission_handler_apple/CHANGELOG.md @@ -1,6 +1,12 @@ ## 9.4.8 -* Added support for the new Android 17 permission `ACCESS_LOCAL_NETWORK` +* Adds Swift Package Manager (SPM) support for Flutter 3.24+. Permissions are + enabled automatically based on usage description keys present in `Info.plist` + — no additional configuration required beyond clearing DerivedData once after + changes: `rm -rf ~/Library/Developer/Xcode/DerivedData`. +* Moves ObjC sources to SPM-compatible layout (`Sources/permission_handler_apple/`). + CocoaPods continues to work unchanged. +* Bumps minimum iOS deployment target to 12.0. ## 9.4.7 diff --git a/permission_handler_apple/example/README.md b/permission_handler_apple/example/README.md index cca8fca64..acc6dde68 100644 --- a/permission_handler_apple/example/README.md +++ b/permission_handler_apple/example/README.md @@ -14,3 +14,14 @@ A few resources to get you started if this is your first Flutter project: For help getting started with Flutter, view our [online documentation](https://flutter.io/docs), which offers tutorials, samples, guidance on mobile development, and a full API reference. + +## Testing constraints + +Some permissions cannot be tested in all environments: + +| Permission | Constraint | +|---|---| +| `assistant` (Siri) | Requires the `com.apple.developer.siri` entitlement in a provisioned app — **not testable on simulator or without a paid developer account**. Adding `NSSiriUsageDescription` to `Info.plist` without this entitlement will crash the app on launch. | +| `bluetooth` | Requires a **physical device** — Bluetooth is not available on the iOS simulator. | +| `locationAlways` | Requires a physical device and the `NSLocationAlwaysAndWhenInUseUsageDescription` key. | +| `appTrackingTransparency` | Dialog is only shown on iOS 14+ physical devices; always returns `authorized` on the simulator. | diff --git a/permission_handler_apple/example/ios/Flutter/AppFrameworkInfo.plist b/permission_handler_apple/example/ios/Flutter/AppFrameworkInfo.plist index 7c5696400..391a902b2 100644 --- a/permission_handler_apple/example/ios/Flutter/AppFrameworkInfo.plist +++ b/permission_handler_apple/example/ios/Flutter/AppFrameworkInfo.plist @@ -20,7 +20,5 @@ ???? CFBundleVersion 1.0 - MinimumOSVersion - 12.0 diff --git a/permission_handler_apple/example/ios/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage/Package.swift b/permission_handler_apple/example/ios/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage/Package.swift new file mode 100644 index 000000000..41fdeba8c --- /dev/null +++ b/permission_handler_apple/example/ios/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage/Package.swift @@ -0,0 +1,32 @@ +// swift-tools-version: 5.9 +// The swift-tools-version declares the minimum version of Swift required to build this package. +// +// Generated file. Do not edit. +// + +import PackageDescription + +let package = Package( + name: "FlutterGeneratedPluginSwiftPackage", + platforms: [ + .iOS("13.0") + ], + products: [ + .library(name: "FlutterGeneratedPluginSwiftPackage", type: .static, targets: ["FlutterGeneratedPluginSwiftPackage"]) + ], + dependencies: [ + .package(name: "permission_handler_apple", path: "../.packages/permission_handler_apple"), + .package(name: "url_launcher_ios", path: "../.packages/url_launcher_ios-6.4.1"), + .package(name: "FlutterFramework", path: "../.packages/FlutterFramework") + ], + targets: [ + .target( + name: "FlutterGeneratedPluginSwiftPackage", + dependencies: [ + .product(name: "permission-handler-apple", package: "permission_handler_apple"), + .product(name: "url-launcher-ios", package: "url_launcher_ios"), + .product(name: "FlutterFramework", package: "FlutterFramework") + ] + ) + ] +) diff --git a/permission_handler_apple/example/ios/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage/Sources/FlutterGeneratedPluginSwiftPackage/FlutterGeneratedPluginSwiftPackage.swift b/permission_handler_apple/example/ios/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage/Sources/FlutterGeneratedPluginSwiftPackage/FlutterGeneratedPluginSwiftPackage.swift new file mode 100644 index 000000000..a30d95a81 --- /dev/null +++ b/permission_handler_apple/example/ios/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage/Sources/FlutterGeneratedPluginSwiftPackage/FlutterGeneratedPluginSwiftPackage.swift @@ -0,0 +1,3 @@ +// +// Generated file. Do not edit. +// diff --git a/permission_handler_apple/example/ios/Flutter/ephemeral/flutter_lldb_helper.py b/permission_handler_apple/example/ios/Flutter/ephemeral/flutter_lldb_helper.py new file mode 100644 index 000000000..a88caf99d --- /dev/null +++ b/permission_handler_apple/example/ios/Flutter/ephemeral/flutter_lldb_helper.py @@ -0,0 +1,32 @@ +# +# Generated file, do not edit. +# + +import lldb + +def handle_new_rx_page(frame: lldb.SBFrame, bp_loc, extra_args, intern_dict): + """Intercept NOTIFY_DEBUGGER_ABOUT_RX_PAGES and touch the pages.""" + base = frame.register["x0"].GetValueAsAddress() + page_len = frame.register["x1"].GetValueAsUnsigned() + + # Note: NOTIFY_DEBUGGER_ABOUT_RX_PAGES will check contents of the + # first page to see if handled it correctly. This makes diagnosing + # misconfiguration (e.g. missing breakpoint) easier. + data = bytearray(page_len) + data[0:8] = b'IHELPED!' + + error = lldb.SBError() + frame.GetThread().GetProcess().WriteMemory(base, data, error) + if not error.Success(): + print(f'Failed to write into {base}[+{page_len}]', error) + return + +def __lldb_init_module(debugger: lldb.SBDebugger, _): + target = debugger.GetDummyTarget() + # Caveat: must use BreakpointCreateByRegEx here and not + # BreakpointCreateByName. For some reasons callback function does not + # get carried over from dummy target for the later. + bp = target.BreakpointCreateByRegex("^NOTIFY_DEBUGGER_ABOUT_RX_PAGES$") + bp.SetScriptCallbackFunction('{}.handle_new_rx_page'.format(__name__)) + bp.SetAutoContinue(True) + print("-- LLDB integration loaded --") diff --git a/permission_handler_apple/example/ios/Flutter/ephemeral/flutter_lldbinit b/permission_handler_apple/example/ios/Flutter/ephemeral/flutter_lldbinit new file mode 100644 index 000000000..e3ba6fbed --- /dev/null +++ b/permission_handler_apple/example/ios/Flutter/ephemeral/flutter_lldbinit @@ -0,0 +1,5 @@ +# +# Generated file, do not edit. +# + +command script import --relative-to-command-file flutter_lldb_helper.py diff --git a/permission_handler_apple/example/ios/Flutter/ephemeral/flutter_native_integration.env b/permission_handler_apple/example/ios/Flutter/ephemeral/flutter_native_integration.env new file mode 100644 index 000000000..17ec2cb49 --- /dev/null +++ b/permission_handler_apple/example/ios/Flutter/ephemeral/flutter_native_integration.env @@ -0,0 +1,12 @@ +FLUTTER_ROOT=/Users/au662726/fvm/versions/main +FLUTTER_APPLICATION_PATH=/Users/au662726/github_projects/flutter-permission-handler/permission_handler_apple/example +FLUTTER_FRAMEWORK_SWIFT_PACKAGE_PATH=/Users/au662726/github_projects/flutter-permission-handler/permission_handler_apple/example/ios/Flutter/ephemeral/Packages/.packages/FlutterFramework +COCOAPODS_PARALLEL_CODE_SIGN=true +FLUTTER_TARGET=lib/main.dart +FLUTTER_BUILD_DIR=build +FLUTTER_BUILD_NAME=1.0.0 +FLUTTER_BUILD_NUMBER=1 +DART_OBFUSCATION=false +TRACK_WIDGET_CREATION=true +TREE_SHAKE_ICONS=false +PACKAGE_CONFIG=.dart_tool/package_config.json diff --git a/permission_handler_apple/example/ios/Podfile b/permission_handler_apple/example/ios/Podfile index bdbed18e3..4bcee9ab6 100644 --- a/permission_handler_apple/example/ios/Podfile +++ b/permission_handler_apple/example/ios/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -# platform :ios, '12.0' +platform :ios, '13.0' # CocoaPods analytics sends network stats synchronously affecting flutter build latency. ENV['COCOAPODS_DISABLE_STATS'] = 'true' diff --git a/permission_handler_apple/example/ios/Runner.xcodeproj/project.pbxproj b/permission_handler_apple/example/ios/Runner.xcodeproj/project.pbxproj index 705be7680..b19cad307 100644 --- a/permission_handler_apple/example/ios/Runner.xcodeproj/project.pbxproj +++ b/permission_handler_apple/example/ios/Runner.xcodeproj/project.pbxproj @@ -10,6 +10,7 @@ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; }; 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; }; 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; }; + 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; }; 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; }; 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; @@ -35,6 +36,7 @@ 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 862A53EA392D32566500E869 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; }; @@ -55,6 +57,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */, B501E7F22BA22C455255CE2E /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; @@ -83,6 +86,7 @@ 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( + 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */, 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 9740EEB21CF90195004384FC /* Debug.xcconfig */, 7AFA3C8E1D35360C0083082E /* Release.xcconfig */, @@ -140,14 +144,15 @@ 97C146EC1CF9000F007C117D /* Resources */, 9705A1C41CF9048500538489 /* Embed Frameworks */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */, - D38B08CB85942E5D11545EE3 /* [CP] Embed Pods Frameworks */, - A7B07F67421488A414C73AAD /* [CP] Copy Pods Resources */, ); buildRules = ( ); dependencies = ( ); name = Runner; + packageProductDependencies = ( + 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */, + ); productName = Runner; productReference = 97C146EE1CF9000F007C117D /* Runner.app */; productType = "com.apple.product-type.application"; @@ -176,6 +181,9 @@ Base, ); mainGroup = 97C146E51CF9000F007C117D; + packageReferences = ( + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */, + ); productRefGroup = 97C146EF1CF9000F007C117D /* Products */; projectDirPath = ""; projectRoot = ""; @@ -253,40 +261,6 @@ shellPath = /bin/sh; shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build"; }; - A7B07F67421488A414C73AAD /* [CP] Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Copy Pods Resources"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; - D38B08CB85942E5D11545EE3 /* [CP] Embed Pods Frameworks */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist", - ); - name = "[CP] Embed Pods Frameworks"; - outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; - showEnvVarsInLog = 0; - }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -362,7 +336,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -448,7 +422,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -497,7 +471,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 13.0; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SUPPORTED_PLATFORMS = iphoneos; @@ -594,6 +568,20 @@ defaultConfigurationName = Release; }; /* End XCConfigurationList section */ + +/* Begin XCLocalSwiftPackageReference section */ + 781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */ = { + isa = XCLocalSwiftPackageReference; + relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; + }; +/* End XCLocalSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */ = { + isa = XCSwiftPackageProductDependency; + productName = FlutterGeneratedPluginSwiftPackage; + }; +/* End XCSwiftPackageProductDependency section */ }; rootObject = 97C146E61CF9000F007C117D /* Project object */; } diff --git a/permission_handler_apple/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/permission_handler_apple/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme index e67b2808a..16b76ec3c 100644 --- a/permission_handler_apple/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme +++ b/permission_handler_apple/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme @@ -1,10 +1,28 @@ + version = "1.7"> + + + + + + + + + + - - - - + + @@ -61,8 +80,6 @@ ReferencedContainer = "container:Runner.xcodeproj"> - - Bool { - GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } + + func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) { + GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry) + } } diff --git a/permission_handler_apple/example/ios/Runner/Info.plist b/permission_handler_apple/example/ios/Runner/Info.plist index e31eecab1..56e40159b 100644 --- a/permission_handler_apple/example/ios/Runner/Info.plist +++ b/permission_handler_apple/example/ios/Runner/Info.plist @@ -2,6 +2,8 @@ + CADisableMinimumFrameDurationOnPhone + CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleExecutable @@ -22,6 +24,67 @@ $(FLUTTER_BUILD_NUMBER) LSRequiresIPhoneOS + NSAppleMusicUsageDescription + Music! + NSBluetoothAlwaysUsageDescription + bluetooth + NSBluetoothPeripheralUsageDescription + bluetooth + NSCalendarsFullAccessUsageDescription + Calendar full access + NSCalendarsUsageDescription + Calendars + NSCalendarsWriteOnlyAccessUsageDescription + Calendar write only + NSCameraUsageDescription + camera + NSContactsUsageDescription + contacts + NSLocationAlwaysAndWhenInUseUsageDescription + Always and when in use! + NSLocationAlwaysUsageDescription + Can I have location always? + NSLocationUsageDescription + Older devices need location. + NSLocationWhenInUseUsageDescription + Need location when in use + NSMicrophoneUsageDescription + microphone + NSMotionUsageDescription + motion + NSPhotoLibraryAddUsageDescription + photos add only + NSPhotoLibraryUsageDescription + photos + NSRemindersUsageDescription + reminders +NSSpeechRecognitionUsageDescription + speech + NSUserTrackingUsageDescription + appTrackingTransparency + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + UIWindowSceneSessionRoleApplication + + + UISceneClassName + UIWindowScene + UISceneConfigurationName + flutter + UISceneDelegateClassName + FlutterSceneDelegate + UISceneStoryboardFile + Main + + + + + UIApplicationSupportsIndirectInputEvents + UILaunchStoryboardName LaunchScreen UIMainStoryboardFile @@ -41,74 +104,7 @@ UIViewControllerBasedStatusBarAppearance - - - NSLocationWhenInUseUsageDescription - Need location when in use - NSLocationAlwaysAndWhenInUseUsageDescription - Always and when in use! - NSLocationUsageDescription - Older devices need location. - NSLocationAlwaysUsageDescription - Can I have location always? - - - NSAppleMusicUsageDescription - Music! - kTCCServiceMediaLibrary - media - - - NSCalendarsUsageDescription - Calendars - NSCalendarsFullAccessUsageDescription - Calendar full access - - - NSCameraUsageDescription - camera - - - NSContactsUsageDescription - contacts - - - NSMicrophoneUsageDescription - microphone - - - NSSpeechRecognitionUsageDescription - speech - - - NSMotionUsageDescription - motion - - - NSPhotoLibraryUsageDescription - photos - - - NSRemindersUsageDescription - reminders - - - NSBluetoothAlwaysUsageDescription - bluetooth - NSBluetoothPeripheralUsageDescription - bluetooth - - - NSUserTrackingUsageDescription - appTrackingTransparency - - - NSSiriUsageDescription - The example app would like access to Siri Kit to demonstrate requesting authorization. - - CADisableMinimumFrameDurationOnPhone - - UIApplicationSupportsIndirectInputEvents - + kTCCServiceMediaLibrary + media diff --git a/permission_handler_apple/example/ios/Runner/RunnerDebug.entitlements b/permission_handler_apple/example/ios/Runner/RunnerDebug.entitlements index 21d95c45f..6503a8865 100644 --- a/permission_handler_apple/example/ios/Runner/RunnerDebug.entitlements +++ b/permission_handler_apple/example/ios/Runner/RunnerDebug.entitlements @@ -2,7 +2,10 @@ + diff --git a/permission_handler_apple/ios/.gitignore b/permission_handler_apple/ios/.gitignore index 710ec6cf1..3ed647344 100644 --- a/permission_handler_apple/ios/.gitignore +++ b/permission_handler_apple/ios/.gitignore @@ -34,3 +34,7 @@ Icon? .tags* /Flutter/Generated.xcconfig + +# Swift Package Manager +.build/ +*.resolved diff --git a/permission_handler_apple/ios/permission_handler_apple.podspec b/permission_handler_apple/ios/permission_handler_apple.podspec index 81210cb8a..ee0359656 100644 --- a/permission_handler_apple/ios/permission_handler_apple.podspec +++ b/permission_handler_apple/ios/permission_handler_apple.podspec @@ -3,7 +3,7 @@ # Pod::Spec.new do |s| s.name = 'permission_handler_apple' - s.version = '9.3.0' + s.version = '9.4.8' s.summary = 'Permission plugin for Flutter.' s.description = <<-DESC Permission plugin for Flutter. This plugin provides a cross-platform (iOS, Android) API to request and check permissions. @@ -12,12 +12,12 @@ Permission plugin for Flutter. This plugin provides a cross-platform (iOS, Andro s.license = { :file => '../LICENSE' } s.author = { 'Baseflow' => 'hello@baseflow.com' } s.source = { :path => '.' } - s.source_files = 'Classes/**/*' - s.public_header_files = 'Classes/**/*.h' + s.source_files = 'permission_handler_apple/Sources/permission_handler_apple/**/*.{h,m}' + s.public_header_files = 'permission_handler_apple/Sources/permission_handler_apple/include/**/*.h' s.dependency 'Flutter' - s.ios.deployment_target = '8.0' + s.ios.deployment_target = '12.0' s.static_framework = true - s.resource_bundles = {'permission_handler_apple_privacy' => ['Resources/PrivacyInfo.xcprivacy']} + s.resource_bundles = {'permission_handler_apple_privacy' => ['permission_handler_apple/Sources/permission_handler_apple/PrivacyInfo.xcprivacy']} end diff --git a/permission_handler_apple/ios/permission_handler_apple/Package.swift b/permission_handler_apple/ios/permission_handler_apple/Package.swift new file mode 100644 index 000000000..5a9e95281 --- /dev/null +++ b/permission_handler_apple/ios/permission_handler_apple/Package.swift @@ -0,0 +1,156 @@ +// swift-tools-version: 5.9 + +import PackageDescription +import Foundation + +// --------------------------------------------------------------------------- +// Permission configuration +// +// Permissions are resolved in priority order: +// 1. Environment variable (e.g. `launchctl setenv PERMISSION_CAMERA 1` +// or `launchctl setenv PERMISSION_NOTIFICATIONS 0` to explicitly disable) +// 2. Matching key present in the app's Info.plist +// 3. Default: enabled for permissions with no required plist key +// (PERMISSION_NOTIFICATIONS, PERMISSION_CRITICAL_ALERTS), +// disabled for all others. +// +// After changing Info.plist or env vars, clear DerivedData once so Xcode +// re-evaluates this manifest: +// rm -rf ~/Library/Developer/Xcode/DerivedData +// --------------------------------------------------------------------------- + +let env = ProcessInfo.processInfo.environment + +/// Walk up from Package.swift looking for Runner/Info.plist. +/// Works when the package is resolved via Flutter's .symlinks/ directory. +func findInfoPlist() -> [String: Any] { + var dir = URL(fileURLWithPath: #file).deletingLastPathComponent() + for _ in 0..<8 { + let candidate = dir.appendingPathComponent("Runner/Info.plist") + if let plist = NSDictionary(contentsOf: candidate) as? [String: Any] { + return plist + } + dir = dir.deletingLastPathComponent() + } + return [:] +} + +let infoPlist = findInfoPlist() + +/// Return "1" if the env var is set (non-zero), "0" if explicitly set to "0", +/// else "1" if any Info.plist key is present, else `defaultValue`. +func enabled(_ envKey: String, plistKeys: String..., defaultValue: String = "0") -> String { + if let val = env[envKey] { return val == "0" ? "0" : "1" } + for key in plistKeys where infoPlist[key] != nil { return "1" } + return defaultValue +} + +let permissionDefines: [CSetting] = [ + // dart: PermissionGroup.calendar (< iOS 17) + .define("PERMISSION_EVENTS", + to: enabled("PERMISSION_EVENTS", + plistKeys: "NSCalendarsUsageDescription")), + // dart: PermissionGroup.calendarFullAccess (iOS 17+) / PermissionGroup.calendarWriteOnly (iOS 17+) + .define("PERMISSION_EVENTS_FULL_ACCESS", + to: enabled("PERMISSION_EVENTS_FULL_ACCESS", + plistKeys: "NSCalendarsFullAccessUsageDescription", + "NSCalendarsWriteOnlyAccessUsageDescription")), + // dart: PermissionGroup.reminders + .define("PERMISSION_REMINDERS", + to: enabled("PERMISSION_REMINDERS", + plistKeys: "NSRemindersUsageDescription")), + // dart: PermissionGroup.contacts + .define("PERMISSION_CONTACTS", + to: enabled("PERMISSION_CONTACTS", + plistKeys: "NSContactsUsageDescription")), + // dart: PermissionGroup.camera + .define("PERMISSION_CAMERA", + to: enabled("PERMISSION_CAMERA", + plistKeys: "NSCameraUsageDescription")), + // dart: PermissionGroup.microphone + .define("PERMISSION_MICROPHONE", + to: enabled("PERMISSION_MICROPHONE", + plistKeys: "NSMicrophoneUsageDescription")), + // dart: PermissionGroup.speech + .define("PERMISSION_SPEECH_RECOGNIZER", + to: enabled("PERMISSION_SPEECH_RECOGNIZER", + plistKeys: "NSSpeechRecognitionUsageDescription")), + // dart: PermissionGroup.photos / PermissionGroup.photosAddOnly + // NSPhotoLibraryAddUsageDescription alone also enables PhotoPermissionStrategy because the + // native code compiles photosAddOnly support under PERMISSION_PHOTOS. + .define("PERMISSION_PHOTOS", + to: enabled("PERMISSION_PHOTOS", + plistKeys: "NSPhotoLibraryUsageDescription", + "NSPhotoLibraryAddUsageDescription")), + // dart: PermissionGroup.photosAddOnly + .define("PERMISSION_PHOTOS_ADD_ONLY", + to: enabled("PERMISSION_PHOTOS_ADD_ONLY", + plistKeys: "NSPhotoLibraryAddUsageDescription")), + // dart: PermissionGroup.location / locationAlways / locationWhenInUse + .define("PERMISSION_LOCATION", + to: enabled("PERMISSION_LOCATION", + plistKeys: "NSLocationWhenInUseUsageDescription", + "NSLocationAlwaysAndWhenInUseUsageDescription")), + // dart: PermissionGroup.locationWhenInUse (only when locationAlways is NOT needed) + .define("PERMISSION_LOCATION_WHENINUSE", + to: enabled("PERMISSION_LOCATION_WHENINUSE", + plistKeys: "NSLocationWhenInUseUsageDescription")), + // dart: PermissionGroup.locationAlways + .define("PERMISSION_LOCATION_ALWAYS", + to: enabled("PERMISSION_LOCATION_ALWAYS", + plistKeys: "NSLocationAlwaysAndWhenInUseUsageDescription")), + // dart: PermissionGroup.notification (no required Info.plist key — enabled by default) + .define("PERMISSION_NOTIFICATIONS", + to: enabled("PERMISSION_NOTIFICATIONS", defaultValue: "1")), + // dart: PermissionGroup.mediaLibrary + .define("PERMISSION_MEDIA_LIBRARY", + to: enabled("PERMISSION_MEDIA_LIBRARY", + plistKeys: "NSAppleMusicUsageDescription")), + // dart: PermissionGroup.sensors + .define("PERMISSION_SENSORS", + to: enabled("PERMISSION_SENSORS", + plistKeys: "NSMotionUsageDescription")), + // dart: PermissionGroup.bluetooth + .define("PERMISSION_BLUETOOTH", + to: enabled("PERMISSION_BLUETOOTH", + plistKeys: "NSBluetoothAlwaysUsageDescription", + "NSBluetoothPeripheralUsageDescription")), + // dart: PermissionGroup.appTrackingTransparency + .define("PERMISSION_APP_TRACKING_TRANSPARENCY", + to: enabled("PERMISSION_APP_TRACKING_TRANSPARENCY", + plistKeys: "NSUserTrackingUsageDescription")), + // dart: PermissionGroup.criticalAlerts (no required Info.plist key — requires Apple entitlement, + // opt-in via env var: launchctl setenv PERMISSION_CRITICAL_ALERTS 1) + .define("PERMISSION_CRITICAL_ALERTS", + to: enabled("PERMISSION_CRITICAL_ALERTS")), + // dart: PermissionGroup.assistant + .define("PERMISSION_ASSISTANT", + to: enabled("PERMISSION_ASSISTANT", + plistKeys: "NSSiriUsageDescription")), +] + +let package = Package( + name: "permission_handler_apple", + platforms: [ + .iOS("12.0"), + ], + products: [ + .library(name: "permission-handler-apple", targets: ["permission_handler_apple"]), + ], + targets: [ + .target( + name: "permission_handler_apple", + path: "Sources/permission_handler_apple", + resources: [ + .process("PrivacyInfo.xcprivacy"), + ], + publicHeadersPath: "include", + cSettings: [ + .headerSearchPath("."), + .headerSearchPath("strategies"), + .headerSearchPath("util"), + .headerSearchPath("include/permission_handler_apple"), + ] + permissionDefines + ), + ] +) diff --git a/permission_handler_apple/ios/Classes/PermissionHandlerEnums.h b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/PermissionHandlerEnums.h similarity index 100% rename from permission_handler_apple/ios/Classes/PermissionHandlerEnums.h rename to permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/PermissionHandlerEnums.h diff --git a/permission_handler_apple/ios/Classes/PermissionHandlerPlugin.h b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/PermissionHandlerPlugin.h similarity index 100% rename from permission_handler_apple/ios/Classes/PermissionHandlerPlugin.h rename to permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/PermissionHandlerPlugin.h diff --git a/permission_handler_apple/ios/Classes/PermissionHandlerPlugin.m b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/PermissionHandlerPlugin.m similarity index 100% rename from permission_handler_apple/ios/Classes/PermissionHandlerPlugin.m rename to permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/PermissionHandlerPlugin.m diff --git a/permission_handler_apple/ios/Classes/PermissionManager.h b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/PermissionManager.h similarity index 100% rename from permission_handler_apple/ios/Classes/PermissionManager.h rename to permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/PermissionManager.h diff --git a/permission_handler_apple/ios/Classes/PermissionManager.m b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/PermissionManager.m similarity index 100% rename from permission_handler_apple/ios/Classes/PermissionManager.m rename to permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/PermissionManager.m diff --git a/permission_handler_apple/ios/Resources/PrivacyInfo.xcprivacy b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/PrivacyInfo.xcprivacy similarity index 100% rename from permission_handler_apple/ios/Resources/PrivacyInfo.xcprivacy rename to permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/PrivacyInfo.xcprivacy diff --git a/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/include/permission_handler_apple/PermissionHandlerPlugin.h b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/include/permission_handler_apple/PermissionHandlerPlugin.h new file mode 100644 index 000000000..2d3a848d8 --- /dev/null +++ b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/include/permission_handler_apple/PermissionHandlerPlugin.h @@ -0,0 +1,7 @@ +#import + +@class PermissionManager; + +@interface PermissionHandlerPlugin : NSObject +- (instancetype)initWithPermissionManager:(PermissionManager *)permissionManager; +@end diff --git a/permission_handler_apple/ios/Classes/strategies/AppTrackingTransparencyPermissionStrategy.h b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/AppTrackingTransparencyPermissionStrategy.h similarity index 100% rename from permission_handler_apple/ios/Classes/strategies/AppTrackingTransparencyPermissionStrategy.h rename to permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/AppTrackingTransparencyPermissionStrategy.h diff --git a/permission_handler_apple/ios/Classes/strategies/AppTrackingTransparencyPermissionStrategy.m b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/AppTrackingTransparencyPermissionStrategy.m similarity index 100% rename from permission_handler_apple/ios/Classes/strategies/AppTrackingTransparencyPermissionStrategy.m rename to permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/AppTrackingTransparencyPermissionStrategy.m diff --git a/permission_handler_apple/ios/Classes/strategies/AssistantPermissionStrategy.h b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/AssistantPermissionStrategy.h similarity index 100% rename from permission_handler_apple/ios/Classes/strategies/AssistantPermissionStrategy.h rename to permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/AssistantPermissionStrategy.h diff --git a/permission_handler_apple/ios/Classes/strategies/AssistantPermissionStrategy.m b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/AssistantPermissionStrategy.m similarity index 100% rename from permission_handler_apple/ios/Classes/strategies/AssistantPermissionStrategy.m rename to permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/AssistantPermissionStrategy.m diff --git a/permission_handler_apple/ios/Classes/strategies/AudioVideoPermissionStrategy.h b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/AudioVideoPermissionStrategy.h similarity index 100% rename from permission_handler_apple/ios/Classes/strategies/AudioVideoPermissionStrategy.h rename to permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/AudioVideoPermissionStrategy.h diff --git a/permission_handler_apple/ios/Classes/strategies/AudioVideoPermissionStrategy.m b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/AudioVideoPermissionStrategy.m similarity index 100% rename from permission_handler_apple/ios/Classes/strategies/AudioVideoPermissionStrategy.m rename to permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/AudioVideoPermissionStrategy.m diff --git a/permission_handler_apple/ios/Classes/strategies/BackgroundRefreshStrategy.h b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/BackgroundRefreshStrategy.h similarity index 92% rename from permission_handler_apple/ios/Classes/strategies/BackgroundRefreshStrategy.h rename to permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/BackgroundRefreshStrategy.h index 2dfe0032c..2f6797453 100644 --- a/permission_handler_apple/ios/Classes/strategies/BackgroundRefreshStrategy.h +++ b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/BackgroundRefreshStrategy.h @@ -6,6 +6,7 @@ // #import +#import #import "PermissionStrategy.h" NS_ASSUME_NONNULL_BEGIN diff --git a/permission_handler_apple/ios/Classes/strategies/BackgroundRefreshStrategy.m b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/BackgroundRefreshStrategy.m similarity index 100% rename from permission_handler_apple/ios/Classes/strategies/BackgroundRefreshStrategy.m rename to permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/BackgroundRefreshStrategy.m diff --git a/permission_handler_apple/ios/Classes/strategies/BluetoothPermissionStrategy.h b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/BluetoothPermissionStrategy.h similarity index 100% rename from permission_handler_apple/ios/Classes/strategies/BluetoothPermissionStrategy.h rename to permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/BluetoothPermissionStrategy.h diff --git a/permission_handler_apple/ios/Classes/strategies/BluetoothPermissionStrategy.m b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/BluetoothPermissionStrategy.m similarity index 100% rename from permission_handler_apple/ios/Classes/strategies/BluetoothPermissionStrategy.m rename to permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/BluetoothPermissionStrategy.m diff --git a/permission_handler_apple/ios/Classes/strategies/ContactPermissionStrategy.h b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/ContactPermissionStrategy.h similarity index 100% rename from permission_handler_apple/ios/Classes/strategies/ContactPermissionStrategy.h rename to permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/ContactPermissionStrategy.h diff --git a/permission_handler_apple/ios/Classes/strategies/ContactPermissionStrategy.m b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/ContactPermissionStrategy.m similarity index 100% rename from permission_handler_apple/ios/Classes/strategies/ContactPermissionStrategy.m rename to permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/ContactPermissionStrategy.m diff --git a/permission_handler_apple/ios/Classes/strategies/CriticalAlertsPermissionStrategy.h b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/CriticalAlertsPermissionStrategy.h similarity index 95% rename from permission_handler_apple/ios/Classes/strategies/CriticalAlertsPermissionStrategy.h rename to permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/CriticalAlertsPermissionStrategy.h index 44b857f48..fbc332ccd 100644 --- a/permission_handler_apple/ios/Classes/strategies/CriticalAlertsPermissionStrategy.h +++ b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/CriticalAlertsPermissionStrategy.h @@ -10,6 +10,7 @@ #if PERMISSION_CRITICAL_ALERTS +#import #import @interface CriticalAlertsPermissionStrategy : NSObject diff --git a/permission_handler_apple/ios/Classes/strategies/CriticalAlertsPermissionStrategy.m b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/CriticalAlertsPermissionStrategy.m similarity index 100% rename from permission_handler_apple/ios/Classes/strategies/CriticalAlertsPermissionStrategy.m rename to permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/CriticalAlertsPermissionStrategy.m diff --git a/permission_handler_apple/ios/Classes/strategies/EventPermissionStrategy.h b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/EventPermissionStrategy.h similarity index 100% rename from permission_handler_apple/ios/Classes/strategies/EventPermissionStrategy.h rename to permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/EventPermissionStrategy.h diff --git a/permission_handler_apple/ios/Classes/strategies/EventPermissionStrategy.m b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/EventPermissionStrategy.m similarity index 100% rename from permission_handler_apple/ios/Classes/strategies/EventPermissionStrategy.m rename to permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/EventPermissionStrategy.m diff --git a/permission_handler_apple/ios/Classes/strategies/LocationPermissionStrategy.h b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/LocationPermissionStrategy.h similarity index 96% rename from permission_handler_apple/ios/Classes/strategies/LocationPermissionStrategy.h rename to permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/LocationPermissionStrategy.h index 52bcc89dc..082e9d5b4 100644 --- a/permission_handler_apple/ios/Classes/strategies/LocationPermissionStrategy.h +++ b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/LocationPermissionStrategy.h @@ -8,6 +8,7 @@ #if PERMISSION_LOCATION || PERMISSION_LOCATION_WHENINUSE || PERMISSION_LOCATION_ALWAYS +#import #import @interface LocationPermissionStrategy : NSObject diff --git a/permission_handler_apple/ios/Classes/strategies/LocationPermissionStrategy.m b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/LocationPermissionStrategy.m similarity index 100% rename from permission_handler_apple/ios/Classes/strategies/LocationPermissionStrategy.m rename to permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/LocationPermissionStrategy.m diff --git a/permission_handler_apple/ios/Classes/strategies/MediaLibraryPermissionStrategy.h b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/MediaLibraryPermissionStrategy.h similarity index 100% rename from permission_handler_apple/ios/Classes/strategies/MediaLibraryPermissionStrategy.h rename to permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/MediaLibraryPermissionStrategy.h diff --git a/permission_handler_apple/ios/Classes/strategies/MediaLibraryPermissionStrategy.m b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/MediaLibraryPermissionStrategy.m similarity index 100% rename from permission_handler_apple/ios/Classes/strategies/MediaLibraryPermissionStrategy.m rename to permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/MediaLibraryPermissionStrategy.m diff --git a/permission_handler_apple/ios/Classes/strategies/NotificationPermissionStrategy.h b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/NotificationPermissionStrategy.h similarity index 95% rename from permission_handler_apple/ios/Classes/strategies/NotificationPermissionStrategy.h rename to permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/NotificationPermissionStrategy.h index df5a795d6..73059a4b5 100644 --- a/permission_handler_apple/ios/Classes/strategies/NotificationPermissionStrategy.h +++ b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/NotificationPermissionStrategy.h @@ -10,6 +10,7 @@ #if PERMISSION_NOTIFICATIONS +#import #import @interface NotificationPermissionStrategy : NSObject diff --git a/permission_handler_apple/ios/Classes/strategies/NotificationPermissionStrategy.m b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/NotificationPermissionStrategy.m similarity index 100% rename from permission_handler_apple/ios/Classes/strategies/NotificationPermissionStrategy.m rename to permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/NotificationPermissionStrategy.m diff --git a/permission_handler_apple/ios/Classes/strategies/PermissionStrategy.h b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/PermissionStrategy.h similarity index 100% rename from permission_handler_apple/ios/Classes/strategies/PermissionStrategy.h rename to permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/PermissionStrategy.h diff --git a/permission_handler_apple/ios/Classes/strategies/PhonePermissionStrategy.h b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/PhonePermissionStrategy.h similarity index 92% rename from permission_handler_apple/ios/Classes/strategies/PhonePermissionStrategy.h rename to permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/PhonePermissionStrategy.h index a90cfc81f..c36d999b1 100644 --- a/permission_handler_apple/ios/Classes/strategies/PhonePermissionStrategy.h +++ b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/PhonePermissionStrategy.h @@ -6,6 +6,7 @@ // #import +#import #import "PermissionStrategy.h" NS_ASSUME_NONNULL_BEGIN diff --git a/permission_handler_apple/ios/Classes/strategies/PhonePermissionStrategy.m b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/PhonePermissionStrategy.m similarity index 100% rename from permission_handler_apple/ios/Classes/strategies/PhonePermissionStrategy.m rename to permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/PhonePermissionStrategy.m diff --git a/permission_handler_apple/ios/Classes/strategies/PhotoPermissionStrategy.h b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/PhotoPermissionStrategy.h similarity index 100% rename from permission_handler_apple/ios/Classes/strategies/PhotoPermissionStrategy.h rename to permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/PhotoPermissionStrategy.h diff --git a/permission_handler_apple/ios/Classes/strategies/PhotoPermissionStrategy.m b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/PhotoPermissionStrategy.m similarity index 100% rename from permission_handler_apple/ios/Classes/strategies/PhotoPermissionStrategy.m rename to permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/PhotoPermissionStrategy.m diff --git a/permission_handler_apple/ios/Classes/strategies/SensorPermissionStrategy.h b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/SensorPermissionStrategy.h similarity index 100% rename from permission_handler_apple/ios/Classes/strategies/SensorPermissionStrategy.h rename to permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/SensorPermissionStrategy.h diff --git a/permission_handler_apple/ios/Classes/strategies/SensorPermissionStrategy.m b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/SensorPermissionStrategy.m similarity index 100% rename from permission_handler_apple/ios/Classes/strategies/SensorPermissionStrategy.m rename to permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/SensorPermissionStrategy.m diff --git a/permission_handler_apple/ios/Classes/strategies/SpeechPermissionStrategy.h b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/SpeechPermissionStrategy.h similarity index 100% rename from permission_handler_apple/ios/Classes/strategies/SpeechPermissionStrategy.h rename to permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/SpeechPermissionStrategy.h diff --git a/permission_handler_apple/ios/Classes/strategies/SpeechPermissionStrategy.m b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/SpeechPermissionStrategy.m similarity index 100% rename from permission_handler_apple/ios/Classes/strategies/SpeechPermissionStrategy.m rename to permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/SpeechPermissionStrategy.m diff --git a/permission_handler_apple/ios/Classes/strategies/StoragePermissionStrategy.h b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/StoragePermissionStrategy.h similarity index 100% rename from permission_handler_apple/ios/Classes/strategies/StoragePermissionStrategy.h rename to permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/StoragePermissionStrategy.h diff --git a/permission_handler_apple/ios/Classes/strategies/StoragePermissionStrategy.m b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/StoragePermissionStrategy.m similarity index 100% rename from permission_handler_apple/ios/Classes/strategies/StoragePermissionStrategy.m rename to permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/StoragePermissionStrategy.m diff --git a/permission_handler_apple/ios/Classes/strategies/UnknownPermissionStrategy.h b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/UnknownPermissionStrategy.h similarity index 100% rename from permission_handler_apple/ios/Classes/strategies/UnknownPermissionStrategy.h rename to permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/UnknownPermissionStrategy.h diff --git a/permission_handler_apple/ios/Classes/strategies/UnknownPermissionStrategy.m b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/UnknownPermissionStrategy.m similarity index 100% rename from permission_handler_apple/ios/Classes/strategies/UnknownPermissionStrategy.m rename to permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/UnknownPermissionStrategy.m diff --git a/permission_handler_apple/ios/Classes/util/Codec.h b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/util/Codec.h similarity index 100% rename from permission_handler_apple/ios/Classes/util/Codec.h rename to permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/util/Codec.h diff --git a/permission_handler_apple/ios/Classes/util/Codec.m b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/util/Codec.m similarity index 100% rename from permission_handler_apple/ios/Classes/util/Codec.m rename to permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/util/Codec.m From 1869c31f555122e6a17c981b300d98624921b922 Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 3 Jun 2026 14:40:29 +0200 Subject: [PATCH 30/57] Update version to 12.0.2 --- permission_handler/CHANGELOG.md | 4 + permission_handler/README.md | 128 ++++++++++++++++---------------- 2 files changed, 68 insertions(+), 64 deletions(-) diff --git a/permission_handler/CHANGELOG.md b/permission_handler/CHANGELOG.md index 134798ed8..412b200ad 100644 --- a/permission_handler/CHANGELOG.md +++ b/permission_handler/CHANGELOG.md @@ -7,6 +7,10 @@ - **BREAKING CHANGE:** , android compilesdk now set to version `compileSdkVersion 37` - Added support for the new Android 17 permission `ACCESS_LOCAL_NETWORK` +## 12.0.2 + +- Updates the documentation to include instructions on Swift Package Manager (SPM) support. + ## 12.0.1 - Updates the correspondence between permission groups and the key values of Info.plist in the README.md. diff --git a/permission_handler/README.md b/permission_handler/README.md index 3e17adf3e..15a80e1e4 100644 --- a/permission_handler/README.md +++ b/permission_handler/README.md @@ -52,7 +52,70 @@ In general, it's sufficient to add permission only to the `main` version.
-iOS (click to expand) +iOS - Swift Package Manager (click to expand) + +> Requires Flutter 3.24.0 or higher and Xcode 15.0 or higher. + +With SPM, `Package.swift` automatically detects which permissions to enable by reading your app's `Info.plist`. A permission is compiled in when its corresponding usage description key is present: + +| Permission group | Info.plist key | +|---|---| +| `PermissionGroup.calendar` (< iOS 17) | `NSCalendarsUsageDescription` | +| `PermissionGroup.calendarWriteOnly` (iOS 17+) | `NSCalendarsWriteOnlyAccessUsageDescription` | +| `PermissionGroup.calendarFullAccess` (iOS 17+) | `NSCalendarsFullAccessUsageDescription` | +| `PermissionGroup.reminders` | `NSRemindersUsageDescription` | +| `PermissionGroup.contacts` | `NSContactsUsageDescription` | +| `PermissionGroup.camera` | `NSCameraUsageDescription` | +| `PermissionGroup.microphone` | `NSMicrophoneUsageDescription` | +| `PermissionGroup.speech` | `NSSpeechRecognitionUsageDescription` | +| `PermissionGroup.photos` | `NSPhotoLibraryUsageDescription` | +| `PermissionGroup.photosAddOnly` | `NSPhotoLibraryAddUsageDescription` | +| `PermissionGroup.location` / `locationWhenInUse` | `NSLocationWhenInUseUsageDescription` | +| `PermissionGroup.locationAlways` | `NSLocationAlwaysAndWhenInUseUsageDescription` | +| `PermissionGroup.mediaLibrary` | `NSAppleMusicUsageDescription` | +| `PermissionGroup.sensors` | `NSMotionUsageDescription` | +| `PermissionGroup.bluetooth` | `NSBluetoothAlwaysUsageDescription` | +| `PermissionGroup.appTrackingTransparency` | `NSUserTrackingUsageDescription` | +| `PermissionGroup.assistant` | `NSSiriUsageDescription` | +| `PermissionGroup.notification` | *(enabled by default — see below)* | +| `PermissionGroup.criticalAlerts` | *(disabled by default — see below)* | + +Because you must already add these keys to `Info.plist` for any permission to work, no additional configuration file is needed. + +#### Special cases: permissions without an Info.plist key + +**`PermissionGroup.notification`** has no required `Info.plist` key and is **enabled by default**. To opt out, disable it via environment variable before building: + +```bash +# When building from terminal (flutter run / flutter build) +export PERMISSION_NOTIFICATIONS=0 + +# When building from Xcode GUI (set once per Mac session, then restart Xcode) +launchctl setenv PERMISSION_NOTIFICATIONS 0 +``` + +**`PermissionGroup.criticalAlerts`** requires a [special entitlement](https://developer.apple.com/documentation/usernotifications/asking-permission-to-use-notifications) granted by Apple and is **disabled by default** to avoid compiling unused code into apps that don't need it. Enable it explicitly: + +```bash +# When building from terminal +export PERMISSION_CRITICAL_ALERTS=1 + +# When building from Xcode GUI +launchctl setenv PERMISSION_CRITICAL_ALERTS 1 +``` + +**After changing any env var or Info.plist key**, clear Xcode's package cache once so `Package.swift` is re-evaluated: + +```bash +rm -rf ~/Library/Developer/Xcode/DerivedData +``` + +Then run `flutter build ios` or rebuild in Xcode as usual. + +
+ +
+iOS - CocoaPods (click to expand) Add permission to your `Info.plist` file. [Here](https://github.com/Baseflow/flutter-permission-handler/blob/master/permission_handler/example/ios/Runner/Info.plist)'s an example `Info.plist` with a complete list of all possible permissions. @@ -174,69 +237,6 @@ You must list the permission you want to use in your application:
-
-Swift Package Manager (SPM) - -> Requires Flutter 3.24.0 or higher and Xcode 15.0 or higher. - -With SPM, `Package.swift` automatically detects which permissions to enable by reading your app's `Info.plist`. A permission is compiled in when its corresponding usage description key is present: - -| Permission group | Info.plist key | -|---|---| -| `PermissionGroup.calendar` (< iOS 17) | `NSCalendarsUsageDescription` | -| `PermissionGroup.calendarWriteOnly` (iOS 17+) | `NSCalendarsWriteOnlyAccessUsageDescription` | -| `PermissionGroup.calendarFullAccess` (iOS 17+) | `NSCalendarsFullAccessUsageDescription` | -| `PermissionGroup.reminders` | `NSRemindersUsageDescription` | -| `PermissionGroup.contacts` | `NSContactsUsageDescription` | -| `PermissionGroup.camera` | `NSCameraUsageDescription` | -| `PermissionGroup.microphone` | `NSMicrophoneUsageDescription` | -| `PermissionGroup.speech` | `NSSpeechRecognitionUsageDescription` | -| `PermissionGroup.photos` | `NSPhotoLibraryUsageDescription` | -| `PermissionGroup.photosAddOnly` | `NSPhotoLibraryAddUsageDescription` | -| `PermissionGroup.location` / `locationWhenInUse` | `NSLocationWhenInUseUsageDescription` | -| `PermissionGroup.locationAlways` | `NSLocationAlwaysAndWhenInUseUsageDescription` | -| `PermissionGroup.mediaLibrary` | `NSAppleMusicUsageDescription` | -| `PermissionGroup.sensors` | `NSMotionUsageDescription` | -| `PermissionGroup.bluetooth` | `NSBluetoothAlwaysUsageDescription` | -| `PermissionGroup.appTrackingTransparency` | `NSUserTrackingUsageDescription` | -| `PermissionGroup.assistant` | `NSSiriUsageDescription` | -| `PermissionGroup.notification` | *(enabled by default — see below)* | -| `PermissionGroup.criticalAlerts` | *(disabled by default — see below)* | - -Because you must already add these keys to `Info.plist` for any permission to work, no additional configuration file is needed. - -#### Special cases: permissions without an Info.plist key - -**`PermissionGroup.notification`** has no required `Info.plist` key and is **enabled by default**. To opt out, disable it via environment variable before building: - -```bash -# When building from terminal (flutter run / flutter build) -export PERMISSION_NOTIFICATIONS=0 - -# When building from Xcode GUI (set once per Mac session, then restart Xcode) -launchctl setenv PERMISSION_NOTIFICATIONS 0 -``` - -**`PermissionGroup.criticalAlerts`** requires a [special entitlement](https://developer.apple.com/documentation/usernotifications/asking-permission-to-use-notifications) granted by Apple and is **disabled by default** to avoid compiling unused code into apps that don't need it. Enable it explicitly: - -```bash -# When building from terminal -export PERMISSION_CRITICAL_ALERTS=1 - -# When building from Xcode GUI -launchctl setenv PERMISSION_CRITICAL_ALERTS 1 -``` - -**After changing any env var or Info.plist key**, clear Xcode's package cache once so `Package.swift` is re-evaluated: - -```bash -rm -rf ~/Library/Developer/Xcode/DerivedData -``` - -Then run `flutter build ios` or rebuild in Xcode as usual. - -
- ## How to use There are a number of [`Permission`](https://pub.dev/documentation/permission_handler_platform_interface/latest/permission_handler_platform_interface/Permission-class.html#constants)s. From d89e5c0c2b0410c5966cf8fd8c4b060baef911a9 Mon Sep 17 00:00:00 2001 From: Gauhar Date: Mon, 1 Jun 2026 13:29:05 +0500 Subject: [PATCH 31/57] fix typo in README about the compileSdkVersion (#1472) --- permission_handler/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/permission_handler/README.md b/permission_handler/README.md index 15a80e1e4..496043367 100644 --- a/permission_handler/README.md +++ b/permission_handler/README.md @@ -33,7 +33,7 @@ android.useAndroidX=true android.enableJetifier=true ``` -2. Make sure you set the `compileSdkVersion` in your "android/app/build.gradle" file to 33: +2. Make sure you set the `compileSdkVersion` in your "android/app/build.gradle" file to 35: ```gradle android { From 0b5afe89f1d623c75135518ab096f230ece40b67 Mon Sep 17 00:00:00 2001 From: harshit saini Date: Mon, 1 Jun 2026 14:00:05 +0530 Subject: [PATCH 32/57] docs: fix completeSdkVersion typo to compileSdkVersion (#1494) Fix incorrect Android SDK parameter name in documentation. "completeSdkVersion" is not a valid Android parameter. The correct name is "compileSdkVersion". This prevents developer confusion when following the troubleshooting guide. --- permission_handler/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/permission_handler/README.md b/permission_handler/README.md index 496043367..2cf16fe33 100644 --- a/permission_handler/README.md +++ b/permission_handler/README.md @@ -357,7 +357,7 @@ Starting with Android 10, apps are required to first obtain permission to read t ### onRequestPermissionsResult is called without results. What can I do? -It is probably caused by a difference between completeSdkVersion and targetSdkVersion. It can be depending on the flutter version that you use. `targetSdkVersion = flutter.targetSdkVersion` in the app/build.gradle indicates that the targetSdkVersion is flutter version dependant. For more information: [issue 1222](https://github.com/Baseflow/flutter-permission-handler/issues/1222) +It is probably caused by a difference between compileSdkVersion and targetSdkVersion. It can be depending on the flutter version that you use. `targetSdkVersion = flutter.targetSdkVersion` in the app/build.gradle indicates that the targetSdkVersion is flutter version dependant. For more information: [issue 1222](https://github.com/Baseflow/flutter-permission-handler/issues/1222) ### Checking or requesting a permission terminates the application on iOS. What can I do? From 246caae9cc2305d09250308a87844b60f9a0d613 Mon Sep 17 00:00:00 2001 From: AlHomam Sultan Date: Mon, 1 Jun 2026 11:31:07 +0300 Subject: [PATCH 33/57] Improved the iOS Setup section in permission_handler/README.md (#1488) After version 8.0.0, permission handler no longer uses all permissions on iOS, but this was not explained clearly in the README. This is my attempt to fix that small mistake. --- permission_handler/README.md | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/permission_handler/README.md b/permission_handler/README.md index 2cf16fe33..dc411f4da 100644 --- a/permission_handler/README.md +++ b/permission_handler/README.md @@ -120,13 +120,14 @@ Then run `flutter build ios` or rebuild in Xcode as usual. Add permission to your `Info.plist` file. [Here](https://github.com/Baseflow/flutter-permission-handler/blob/master/permission_handler/example/ios/Runner/Info.plist)'s an example `Info.plist` with a complete list of all possible permissions. -> IMPORTANT: ~~You will have to include all permission options when you want to submit your App.~~ This is because the `permission_handler` plugin touches all different SDKs and because the static code analyzer (run by Apple upon App submission) detects this and will assert if it cannot find a matching permission option in the `Info.plist`. More information about this can be found [here](https://github.com/Baseflow/flutter-permission-handler/issues/26). +> IMPORTANT: ~~You will have to include all permission options when you want to submit your App. This is because the `permission_handler` plugin touches all different SDKs and because the static code analyzer (run by Apple upon App submission) detects this and will assert if it cannot find a matching permission option in the `Info.plist`. More information about this can be found [here](https://github.com/Baseflow/flutter-permission-handler/issues/26).~~ + This has been fixed since version 8.0.0, now permission_handler by default excludes all permissions and developers only have to enable those that the app really needs. The permission_handler plugin use [macros](https://github.com/Baseflow/flutter-permission-handler/blob/master/permission_handler_apple/ios/Classes/PermissionHandlerEnums.h) to control whether a permission is enabled. You must list the permission you want to use in your application: -1. Add the following to your `Podfile` file: +1. Add the following to your `Podfile`'s `post_install` block: ```ruby post_install do |installer| @@ -136,7 +137,8 @@ You must list the permission you want to use in your application: target.build_configurations.each do |config| # You can remove unused permissions here # for more information: https://github.com/Baseflow/flutter-permission-handler/blob/main/permission_handler_apple/ios/Classes/PermissionHandlerEnums.h - # e.g. when you don't need camera permission, just add 'PERMISSION_CAMERA=0' + # When you don't need a permission, just change its value to 0 + # e.g. 'PERMISSION_CAMERA=0' instead of 'PERMISSION_CAMERA=1' config.build_settings['GCC_PREPROCESSOR_DEFINITIONS'] ||= [ '$(inherited)', @@ -199,16 +201,18 @@ You must list the permission you want to use in your application: end ``` -2. Remove the `#` character in front of the permission you want to use. For example, if you need access to the calendar make sure the code looks like this: +2. For the permissions you *want* to use, keep them as is. For example, if you need access to the calendar make sure the code looks like this: ```ruby ## dart: PermissionGroup.calendar 'PERMISSION_EVENTS=1', ``` +3. When you **DON'T** need a permission, change its value to `0` e.g. `'PERMISSION_CAMERA=0'` instead of `'PERMISSION_CAMERA=1'` -3. Delete the corresponding permission description in `Info.plist` - e.g. when you don't need camera permission, just delete 'NSCameraUsageDescription' - The following lists the relationship between `Permission` and `The key of Info.plist`: +3. And delete the corresponding permission description in `Info.plist` + e.g. when you don't need camera permission, just delete `'NSCameraUsageDescription'` + +The following lists the relationship between `Permission` and `The key of Info.plist`: | Permission | Info.plist | Macro | |---------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------------------------|----------------------------------------| From ccdb98d8762f8aec74b7f0f46a2e949b8e97ac85 Mon Sep 17 00:00:00 2001 From: Maurits van Beusekom Date: Mon, 1 Jun 2026 11:49:04 +0200 Subject: [PATCH 34/57] Rewrite copyleft code from stackoverflow > > Co-authored-by: Novarest --- permission_handler_apple/example/.gitignore | 1 + .../ios/Runner.xcodeproj/project.pbxproj | 4 ++++ permission_handler_apple/example/pubspec.yaml | 2 +- .../strategies/PhonePermissionStrategy.m | 18 +++++++++--------- 4 files changed, 15 insertions(+), 10 deletions(-) diff --git a/permission_handler_apple/example/.gitignore b/permission_handler_apple/example/.gitignore index 2156e772e..260fe82ac 100644 --- a/permission_handler_apple/example/.gitignore +++ b/permission_handler_apple/example/.gitignore @@ -60,6 +60,7 @@ build/ **/ios/Flutter/app.flx **/ios/Flutter/app.zip **/ios/Flutter/flutter_assets/ +**/ios/Flutter/ephemeral/ **/ios/ServiceDefinitions.json **/ios/Runner/GeneratedPluginRegistrant.* diff --git a/permission_handler_apple/example/ios/Runner.xcodeproj/project.pbxproj b/permission_handler_apple/example/ios/Runner.xcodeproj/project.pbxproj index b19cad307..ee00f0144 100644 --- a/permission_handler_apple/example/ios/Runner.xcodeproj/project.pbxproj +++ b/permission_handler_apple/example/ios/Runner.xcodeproj/project.pbxproj @@ -36,6 +36,8 @@ 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; }; 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; }; 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + 784666492D4C4C64000A1A5F /* FlutterFramework */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterFramework; path = Flutter/ephemeral/Packages/.packages/FlutterFramework; sourceTree = ""; }; + 78DABEA22ED26510000E7860 /* permission_handler_apple */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = permission_handler_apple; path = ../../ios/permission_handler_apple; sourceTree = ""; }; 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; }; 862A53EA392D32566500E869 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; @@ -86,6 +88,8 @@ 9740EEB11CF90186004384FC /* Flutter */ = { isa = PBXGroup; children = ( + 78DABEA22ED26510000E7860 /* permission_handler_apple */, + 784666492D4C4C64000A1A5F /* FlutterFramework */, 78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */, 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */, 9740EEB21CF90195004384FC /* Debug.xcconfig */, diff --git a/permission_handler_apple/example/pubspec.yaml b/permission_handler_apple/example/pubspec.yaml index 81b6f2dc4..71aaacd79 100644 --- a/permission_handler_apple/example/pubspec.yaml +++ b/permission_handler_apple/example/pubspec.yaml @@ -21,7 +21,7 @@ dev_dependencies: # the parent directory to use the current plugin's version. path: ../ - url_launcher: ^6.0.12 + url_launcher: ^6.3.2 flutter: uses-material-design: true diff --git a/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/PhonePermissionStrategy.m b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/PhonePermissionStrategy.m index 37222849d..6944a9835 100644 --- a/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/PhonePermissionStrategy.m +++ b/permission_handler_apple/ios/permission_handler_apple/Sources/permission_handler_apple/strategies/PhonePermissionStrategy.m @@ -17,8 +17,9 @@ - (PermissionStatus)checkPermissionStatus:(PermissionGroup)permission { } - (void)checkServiceStatus:(PermissionGroup)permission completionHandler:(ServiceStatusHandler)completionHandler { - // https://stackoverflow.com/a/5095058 - if (![[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"tel://"]]) { + UIApplication *app = [UIApplication sharedApplication]; + NSURL *telURL = [NSURL URLWithString:@"tel://"]; + if (![app canOpenURL:telURL]) { completionHandler(ServiceStatusNotApplicable); } completionHandler([self canDevicePlaceAPhoneCall] ? ServiceStatusEnabled : ServiceStatusDisabled); @@ -52,15 +53,14 @@ -(bool) canDevicePlaceAPhoneCall { } -(bool)canPlacePhoneCallWithCarrier:(CTCarrier *)carrier { - // https://stackoverflow.com/a/11595365 - NSString *mnc = [carrier mobileNetworkCode]; - if (([mnc length] == 0) || ([mnc isEqualToString:@"65535"])) { - // Device cannot place a call at this time. SIM might be removed. + NSString *networkCode = [carrier mobileNetworkCode]; + if (networkCode.length == 0 || [networkCode isEqualToString:@"65535"]) { + // Device is unable to initiate a call at this time. SIM might be missing. return NO; - } else { - // Device can place a phone call - return YES; } + + // Mobile Network Code is valid and device can initiate a call + return YES; } @end From eb78117ff676fc0f859baab04ae7e5e77c3bbd4c Mon Sep 17 00:00:00 2001 From: Maurits van Beusekom Date: Mon, 1 Jun 2026 11:57:24 +0200 Subject: [PATCH 35/57] Bump permission_handler_apple to 9.4.9 --- permission_handler_apple/CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/permission_handler_apple/CHANGELOG.md b/permission_handler_apple/CHANGELOG.md index 05a0f3485..f60ecef2a 100644 --- a/permission_handler_apple/CHANGELOG.md +++ b/permission_handler_apple/CHANGELOG.md @@ -1,3 +1,7 @@ +## 9.4.9 + +* Rewrites copyleft code from stackoverflow to fix compliance issue. + ## 9.4.8 * Adds Swift Package Manager (SPM) support for Flutter 3.24+. Permissions are From d6cf58e925ab5525565b06d05386377d07e0d28f Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 3 Jun 2026 14:41:02 +0200 Subject: [PATCH 36/57] Bump permission_handler to 12.0.3 --- permission_handler/CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/permission_handler/CHANGELOG.md b/permission_handler/CHANGELOG.md index 412b200ad..df454a31e 100644 --- a/permission_handler/CHANGELOG.md +++ b/permission_handler/CHANGELOG.md @@ -7,6 +7,11 @@ - **BREAKING CHANGE:** , android compilesdk now set to version `compileSdkVersion 37` - Added support for the new Android 17 permission `ACCESS_LOCAL_NETWORK` +## 12.0.3 + +- Rewrites the "iOS - CocaoPods" section in the README.md to match version 8.0.0 of the permission_handler. +- Fixes several smaller typo's in the README.md. + ## 12.0.2 - Updates the documentation to include instructions on Swift Package Manager (SPM) support. From 01be4d6c2d709e24270204cbca74bf4f37dff352 Mon Sep 17 00:00:00 2001 From: Maurits van Beusekom Date: Mon, 1 Jun 2026 12:05:04 +0200 Subject: [PATCH 37/57] Bump permission_handler_apple to 9.4.9 --- permission_handler_apple/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/permission_handler_apple/pubspec.yaml b/permission_handler_apple/pubspec.yaml index 496e1aca6..a03947478 100644 --- a/permission_handler_apple/pubspec.yaml +++ b/permission_handler_apple/pubspec.yaml @@ -2,7 +2,7 @@ name: permission_handler_apple description: Permission plugin for Flutter. This plugin provides the iOS API to request and check permissions. repository: https://github.com/baseflow/flutter-permission-handler issue_tracker: https://github.com/Baseflow/flutter-permission-handler/issues -version: 9.4.8 +version: 9.4.9 environment: sdk: ">=2.18.0 <4.0.0" From 653e93b9f56363a12c95059ca1da9073d4285ae1 Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 3 Jun 2026 14:43:53 +0200 Subject: [PATCH 38/57] Added ACCESS_LOCAL_NETWORK permission for android 17 --- .../java/com/baseflow/permissionhandler/PermissionUtils.java | 1 + permission_handler_apple/CHANGELOG.md | 1 + 2 files changed, 2 insertions(+) diff --git a/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionUtils.java b/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionUtils.java index 35cc35e2d..a210d9570 100644 --- a/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionUtils.java +++ b/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionUtils.java @@ -620,6 +620,7 @@ static List getManifestNames( break; case PermissionConstants.PERMISSION_GROUP_MEDIA_LIBRARY: case PermissionConstants.PERMISSION_GROUP_REMINDERS: + case PermissionConstants.PERMISSION_GROUP_ACCESS_LOCAL_NETWORK: case PermissionConstants.PERMISSION_GROUP_UNKNOWN: return null; } diff --git a/permission_handler_apple/CHANGELOG.md b/permission_handler_apple/CHANGELOG.md index f60ecef2a..ace8017b1 100644 --- a/permission_handler_apple/CHANGELOG.md +++ b/permission_handler_apple/CHANGELOG.md @@ -1,6 +1,7 @@ ## 9.4.9 * Rewrites copyleft code from stackoverflow to fix compliance issue. +* Added support for the new Android 17 permission `ACCESS_LOCAL_NETWORK` ## 9.4.8 From 5fc38c8ebeba08d83ff3aa473244d0ce99754529 Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 3 Jun 2026 10:40:23 +0200 Subject: [PATCH 39/57] bump main package version --- permission_handler/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/permission_handler/CHANGELOG.md b/permission_handler/CHANGELOG.md index df454a31e..1cf60f1a6 100644 --- a/permission_handler/CHANGELOG.md +++ b/permission_handler/CHANGELOG.md @@ -15,6 +15,7 @@ ## 12.0.2 - Updates the documentation to include instructions on Swift Package Manager (SPM) support. +- Added support for the new Android 17 permission `ACCESS_LOCAL_NETWORK` ## 12.0.1 From 765bae35d588cd3904181973029d9d77c41e8752 Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 3 Jun 2026 14:44:23 +0200 Subject: [PATCH 40/57] missing defs --- permission_handler/CHANGELOG.md | 1 - 1 file changed, 1 deletion(-) diff --git a/permission_handler/CHANGELOG.md b/permission_handler/CHANGELOG.md index 1cf60f1a6..df454a31e 100644 --- a/permission_handler/CHANGELOG.md +++ b/permission_handler/CHANGELOG.md @@ -15,7 +15,6 @@ ## 12.0.2 - Updates the documentation to include instructions on Swift Package Manager (SPM) support. -- Added support for the new Android 17 permission `ACCESS_LOCAL_NETWORK` ## 12.0.1 From 2e642c070e7c37fe2080ad44782709760403dcab Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 3 Jun 2026 10:46:26 +0200 Subject: [PATCH 41/57] dart formatting --- permission_handler/example/lib/main.dart | 92 +++--- .../test/permission_handler_test.dart | 93 +++--- .../example/lib/main.dart | 52 ++-- .../example/lib/main.dart | 70 +++-- permission_handler_html/example/lib/main.dart | 97 +++--- .../lib/permission_handler_html.dart | 17 +- permission_handler_html/lib/web_delegate.dart | 30 +- .../method_channel_permission_handler.dart | 29 +- .../lib/src/method_channel/utils/codec.dart | 11 +- ...permission_handler_platform_interface.dart | 9 +- .../method_channel/method_channel_mock.dart | 6 +- ...ethod_channel_permission_handler_test.dart | 284 +++++++++--------- .../src/method_channel/utils/coded_test.dart | 7 +- ...ssion_handler_platform_interface_test.dart | 113 +++---- .../test/src/permission_status_test.dart | 55 ++-- .../test/src/permissions_test.dart | 70 ++--- .../test/src/service_status_test.dart | 18 +- .../example/lib/main.dart | 66 ++-- 18 files changed, 604 insertions(+), 515 deletions(-) diff --git a/permission_handler/example/lib/main.dart b/permission_handler/example/lib/main.dart index e37e51302..7a6ab62bc 100644 --- a/permission_handler/example/lib/main.dart +++ b/permission_handler/example/lib/main.dart @@ -43,41 +43,40 @@ class _PermissionHandlerWidgetState extends State { Widget build(BuildContext context) { return Center( child: ListView( - children: - Permission.values - .where((permission) { - if (Platform.isIOS) { - return permission != Permission.unknown && - permission != Permission.phone && - permission != Permission.sms && - permission != Permission.ignoreBatteryOptimizations && - permission != Permission.accessMediaLocation && - permission != Permission.activityRecognition && - permission != Permission.manageExternalStorage && - permission != Permission.systemAlertWindow && - permission != Permission.requestInstallPackages && - permission != Permission.accessNotificationPolicy && - permission != Permission.bluetoothScan && - permission != Permission.bluetoothAdvertise && - permission != Permission.bluetoothConnect && - permission != Permission.nearbyWifiDevices && - permission != Permission.videos && - permission != Permission.audio && - permission != Permission.scheduleExactAlarm && - permission != Permission.sensorsAlways; - } else { - return permission != Permission.unknown && - permission != Permission.mediaLibrary && - permission != Permission.photosAddOnly && - permission != Permission.reminders && - permission != Permission.bluetooth && - permission != Permission.appTrackingTransparency && - permission != Permission.criticalAlerts && - permission != Permission.assistant; - } - }) - .map((permission) => PermissionWidget(permission)) - .toList(), + children: Permission.values + .where((permission) { + if (Platform.isIOS) { + return permission != Permission.unknown && + permission != Permission.phone && + permission != Permission.sms && + permission != Permission.ignoreBatteryOptimizations && + permission != Permission.accessMediaLocation && + permission != Permission.activityRecognition && + permission != Permission.manageExternalStorage && + permission != Permission.systemAlertWindow && + permission != Permission.requestInstallPackages && + permission != Permission.accessNotificationPolicy && + permission != Permission.bluetoothScan && + permission != Permission.bluetoothAdvertise && + permission != Permission.bluetoothConnect && + permission != Permission.nearbyWifiDevices && + permission != Permission.videos && + permission != Permission.audio && + permission != Permission.scheduleExactAlarm && + permission != Permission.sensorsAlways; + } else { + return permission != Permission.unknown && + permission != Permission.mediaLibrary && + permission != Permission.photosAddOnly && + permission != Permission.reminders && + permission != Permission.bluetooth && + permission != Permission.appTrackingTransparency && + permission != Permission.criticalAlerts && + permission != Permission.assistant; + } + }) + .map((permission) => PermissionWidget(permission)) + .toList(), ), ); } @@ -136,18 +135,17 @@ class _PermissionState extends State { _permissionStatus.toString(), style: TextStyle(color: getPermissionColor()), ), - trailing: - (widget.permission is PermissionWithService) - ? IconButton( - icon: const Icon(Icons.info, color: Colors.white), - onPressed: () { - checkServiceStatus( - context, - widget.permission as PermissionWithService, - ); - }, - ) - : null, + trailing: (widget.permission is PermissionWithService) + ? IconButton( + icon: const Icon(Icons.info, color: Colors.white), + onPressed: () { + checkServiceStatus( + context, + widget.permission as PermissionWithService, + ); + }, + ) + : null, onTap: () { requestPermission(widget.permission); }, diff --git a/permission_handler/test/permission_handler_test.dart b/permission_handler/test/permission_handler_test.dart index ae666e9a2..4b51c142c 100644 --- a/permission_handler/test/permission_handler_test.dart +++ b/permission_handler/test/permission_handler_test.dart @@ -23,21 +23,27 @@ void main() { }); test( - // ignore: lines_longer_than_80_chars - 'PermissionActions on Permission: get shouldShowRequestRationale should return true when on android', - () async { - final mockPermissionHandlerPlatform = PermissionHandlerPlatform.instance; - - when(mockPermissionHandlerPlatform - .shouldShowRequestPermissionRationale(Permission.contacts)) - .thenAnswer((_) => Future.value(true)); - - await Permission.contacts.shouldShowRequestRationale; - - verify(mockPermissionHandlerPlatform - .shouldShowRequestPermissionRationale(Permission.contacts)) - .called(1); - }); + // ignore: lines_longer_than_80_chars + 'PermissionActions on Permission: get shouldShowRequestRationale should return true when on android', + () async { + final mockPermissionHandlerPlatform = + PermissionHandlerPlatform.instance; + + when( + mockPermissionHandlerPlatform.shouldShowRequestPermissionRationale( + Permission.contacts, + ), + ).thenAnswer((_) => Future.value(true)); + + await Permission.contacts.shouldShowRequestRationale; + + verify( + mockPermissionHandlerPlatform.shouldShowRequestPermissionRationale( + Permission.contacts, + ), + ).called(1); + }, + ); test('PermissionActions on Permission: request()', () async { final permissionRequest = Permission.contacts.request(); @@ -65,11 +71,14 @@ void main() { expect(isLimited, false); }); - test('PermissionCheckShortcuts on Permission: get isPermanentlyDenied', - () async { - final isPermanentlyDenied = await Permission.contacts.isPermanentlyDenied; - expect(isPermanentlyDenied, false); - }); + test( + 'PermissionCheckShortcuts on Permission: get isPermanentlyDenied', + () async { + final isPermanentlyDenied = + await Permission.contacts.isPermanentlyDenied; + expect(isPermanentlyDenied, false); + }, + ); test('PermissionCheckShortcuts on Permission: get isProvisional', () async { final isProvisional = await Permission.contacts.isProvisional; @@ -77,23 +86,25 @@ void main() { }); test( - // ignore: lines_longer_than_80_chars - 'ServicePermissionActions on PermissionWithService: get ServiceStatus returns the right service status', - () async { - var serviceStatus = await Permission.phone.serviceStatus; + // ignore: lines_longer_than_80_chars + 'ServicePermissionActions on PermissionWithService: get ServiceStatus returns the right service status', + () async { + var serviceStatus = await Permission.phone.serviceStatus; - expect(serviceStatus, ServiceStatus.enabled); - }); + expect(serviceStatus, ServiceStatus.enabled); + }, + ); test( - // ignore: lines_longer_than_80_chars - 'PermissionListActions on List: request() on a list returns a Map', - () async { - var permissionList = []; - final permissionMap = await permissionList.request(); - - expect(permissionMap, isA>()); - }); + // ignore: lines_longer_than_80_chars + 'PermissionListActions on List: request() on a list returns a Map', + () async { + var permissionList = []; + final permissionMap = await permissionList.request(); + + expect(permissionMap, isA>()); + }, + ); test('onDeniedCallback sets onDenied', () async { bool callbackCalled = false; @@ -151,7 +162,8 @@ void main() { .onDeniedCallback(() => callbackCalled.add('Denied')) .onGrantedCallback(() => callbackCalled.add('Granted')) .onPermanentlyDeniedCallback( - () => callbackCalled.add('PermanentlyDenied')) + () => callbackCalled.add('PermanentlyDenied'), + ) .onRestrictedCallback(() => callbackCalled.add('Restricted')) .onLimitedCallback(() => callbackCalled.add('Limited')) .onProvisionalCallback(() => callbackCalled.add('Provisional')) @@ -166,8 +178,7 @@ class MockPermissionHandlerPlatform extends Mock with // ignore: prefer_mixin MockPlatformInterfaceMixin - implements - PermissionHandlerPlatform { + implements PermissionHandlerPlatform { @override Future checkPermissionStatus(Permission permission) => Future.value(PermissionStatus.granted); @@ -181,7 +192,8 @@ class MockPermissionHandlerPlatform extends Mock @override Future> requestPermissions( - List permissions) { + List permissions, + ) { var permissionsMap = {}; return Future.value(permissionsMap); } @@ -189,10 +201,7 @@ class MockPermissionHandlerPlatform extends Mock @override Future shouldShowRequestPermissionRationale(Permission? permission) { return super.noSuchMethod( - Invocation.method( - #shouldShowPermissionRationale, - [permission], - ), + Invocation.method(#shouldShowPermissionRationale, [permission]), returnValue: Future.value(true), ); } diff --git a/permission_handler_android/example/lib/main.dart b/permission_handler_android/example/lib/main.dart index 4a0a6e052..f8f49b03d 100644 --- a/permission_handler_android/example/lib/main.dart +++ b/permission_handler_android/example/lib/main.dart @@ -42,21 +42,20 @@ class _PermissionHandlerWidgetState extends State { Widget build(BuildContext context) { return Center( child: ListView( - children: - Permission.values - .where((permission) { - return permission != Permission.unknown && - permission != Permission.mediaLibrary && - permission != Permission.photosAddOnly && - permission != Permission.reminders && - permission != Permission.bluetooth && - permission != Permission.appTrackingTransparency && - permission != Permission.criticalAlerts && - permission != Permission.assistant && - permission != Permission.backgroundRefresh; - }) - .map((permission) => PermissionWidget(permission)) - .toList(), + children: Permission.values + .where((permission) { + return permission != Permission.unknown && + permission != Permission.mediaLibrary && + permission != Permission.photosAddOnly && + permission != Permission.reminders && + permission != Permission.bluetooth && + permission != Permission.appTrackingTransparency && + permission != Permission.criticalAlerts && + permission != Permission.assistant && + permission != Permission.backgroundRefresh; + }) + .map((permission) => PermissionWidget(permission)) + .toList(), ), ); } @@ -118,18 +117,17 @@ class _PermissionState extends State { _permissionStatus.toString(), style: TextStyle(color: getPermissionColor()), ), - trailing: - (widget._permission is PermissionWithService) - ? IconButton( - icon: const Icon(Icons.info, color: Colors.white), - onPressed: () { - checkServiceStatus( - context, - widget._permission as PermissionWithService, - ); - }, - ) - : null, + trailing: (widget._permission is PermissionWithService) + ? IconButton( + icon: const Icon(Icons.info, color: Colors.white), + onPressed: () { + checkServiceStatus( + context, + widget._permission as PermissionWithService, + ); + }, + ) + : null, onTap: () { requestPermission(widget._permission); }, diff --git a/permission_handler_apple/example/lib/main.dart b/permission_handler_apple/example/lib/main.dart index 4750f1ac5..7605e3c48 100644 --- a/permission_handler_apple/example/lib/main.dart +++ b/permission_handler_apple/example/lib/main.dart @@ -41,30 +41,29 @@ class _PermissionHandlerWidgetState extends State { Widget build(BuildContext context) { return Center( child: ListView( - children: - Permission.values - .where((permission) { - return permission != Permission.unknown && - permission != Permission.phone && - permission != Permission.sms && - permission != Permission.ignoreBatteryOptimizations && - permission != Permission.accessMediaLocation && - permission != Permission.activityRecognition && - permission != Permission.manageExternalStorage && - permission != Permission.systemAlertWindow && - permission != Permission.requestInstallPackages && - permission != Permission.accessNotificationPolicy && - permission != Permission.bluetoothScan && - permission != Permission.bluetoothAdvertise && - permission != Permission.bluetoothConnect && - permission != Permission.nearbyWifiDevices && - permission != Permission.videos && - permission != Permission.audio && - permission != Permission.scheduleExactAlarm && - permission != Permission.sensorsAlways; - }) - .map((permission) => PermissionWidget(permission)) - .toList(), + children: Permission.values + .where((permission) { + return permission != Permission.unknown && + permission != Permission.phone && + permission != Permission.sms && + permission != Permission.ignoreBatteryOptimizations && + permission != Permission.accessMediaLocation && + permission != Permission.activityRecognition && + permission != Permission.manageExternalStorage && + permission != Permission.systemAlertWindow && + permission != Permission.requestInstallPackages && + permission != Permission.accessNotificationPolicy && + permission != Permission.bluetoothScan && + permission != Permission.bluetoothAdvertise && + permission != Permission.bluetoothConnect && + permission != Permission.nearbyWifiDevices && + permission != Permission.videos && + permission != Permission.audio && + permission != Permission.scheduleExactAlarm && + permission != Permission.sensorsAlways; + }) + .map((permission) => PermissionWidget(permission)) + .toList(), ), ); } @@ -125,18 +124,17 @@ class _PermissionState extends State { _permissionStatus.toString(), style: TextStyle(color: getPermissionColor()), ), - trailing: - (widget.permission is PermissionWithService) - ? IconButton( - icon: const Icon(Icons.info, color: Colors.white), - onPressed: () { - checkServiceStatus( - context, - widget.permission as PermissionWithService, - ); - }, - ) - : null, + trailing: (widget.permission is PermissionWithService) + ? IconButton( + icon: const Icon(Icons.info, color: Colors.white), + onPressed: () { + checkServiceStatus( + context, + widget.permission as PermissionWithService, + ); + }, + ) + : null, onTap: () { requestPermission(widget.permission); }, diff --git a/permission_handler_html/example/lib/main.dart b/permission_handler_html/example/lib/main.dart index e3650eba8..37ffcf5b3 100644 --- a/permission_handler_html/example/lib/main.dart +++ b/permission_handler_html/example/lib/main.dart @@ -3,29 +3,33 @@ import 'package:flutter/material.dart'; import 'package:permission_handler_platform_interface/permission_handler_platform_interface.dart'; void main() { - runApp(BaseflowPluginExample( + runApp( + BaseflowPluginExample( pluginName: 'Permission Handler', githubURL: 'https://github.com/Baseflow/flutter-permission-handler', pubDevURL: 'https://pub.dev/packages/permission_handler', - pages: [PermissionHandlerWidget.createPage()])); + pages: [PermissionHandlerWidget.createPage()], + ), + ); } ///Defines the main theme color final MaterialColor themeMaterialColor = BaseflowPluginExample.createMaterialColor( - const Color.fromRGBO(48, 49, 60, 1)); + const Color.fromRGBO(48, 49, 60, 1), + ); /// A Flutter application demonstrating the functionality of this plugin class PermissionHandlerWidget extends StatefulWidget { /// Creates a [PermissionHandlerWidget]. - const PermissionHandlerWidget({ - super.key, - }); + const PermissionHandlerWidget({super.key}); /// Create a page containing the functionality of this plugin static ExamplePage createPage() { return ExamplePage( - Icons.location_on, (context) => const PermissionHandlerWidget()); + Icons.location_on, + (context) => const PermissionHandlerWidget(), + ); } @override @@ -38,18 +42,19 @@ class _PermissionHandlerWidgetState extends State { Widget build(BuildContext context) { return Center( child: ListView( - children: Permission.values - .where((permission) { - return permission != Permission.unknown && - permission != Permission.mediaLibrary && - permission != Permission.photos && - permission != Permission.photosAddOnly && - permission != Permission.reminders && - permission != Permission.appTrackingTransparency && - permission != Permission.criticalAlerts; - }) - .map((permission) => PermissionWidget(permission)) - .toList()), + children: Permission.values + .where((permission) { + return permission != Permission.unknown && + permission != Permission.mediaLibrary && + permission != Permission.photos && + permission != Permission.photosAddOnly && + permission != Permission.reminders && + permission != Permission.appTrackingTransparency && + permission != Permission.criticalAlerts; + }) + .map((permission) => PermissionWidget(permission)) + .toList(), + ), ); } } @@ -57,10 +62,7 @@ class _PermissionHandlerWidgetState extends State { /// Permission widget containing information about the passed [Permission] class PermissionWidget extends StatefulWidget { /// Constructs a [PermissionWidget] for the supplied [Permission] - const PermissionWidget( - this._permission, { - super.key, - }); + const PermissionWidget(this._permission, {super.key}); final Permission _permission; @@ -83,9 +85,12 @@ class _PermissionState extends State { } void _listenForPermissionStatus() async { - await _permissionHandler.checkPermissionStatus(widget._permission).then( - (status) => setState(() => _permissionStatus = status), - onError: (error, st) => debugPrint('$error')); + await _permissionHandler + .checkPermissionStatus(widget._permission) + .then( + (status) => setState(() => _permissionStatus = status), + onError: (error, st) => debugPrint('$error'), + ); } Color getPermissionColor() { @@ -114,14 +119,14 @@ class _PermissionState extends State { ), trailing: (widget._permission is PermissionWithService) ? IconButton( - icon: const Icon( - Icons.info, - color: Colors.white, - ), + icon: const Icon(Icons.info, color: Colors.white), onPressed: () { checkServiceStatus( - context, widget._permission as PermissionWithService); - }) + context, + widget._permission as PermissionWithService, + ); + }, + ) : null, onTap: () { requestPermission(widget._permission); @@ -130,18 +135,26 @@ class _PermissionState extends State { } void checkServiceStatus( - BuildContext context, PermissionWithService permission) async { - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text( - (await _permissionHandler.checkServiceStatus(permission)).toString()), - )); + BuildContext context, + PermissionWithService permission, + ) async { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + (await _permissionHandler.checkServiceStatus(permission)).toString(), + ), + ), + ); } Future requestPermission(Permission permission) async { - await _permissionHandler.requestPermissions([permission]).then( - (status) => setState(() { - _permissionStatus = status[permission] ?? PermissionStatus.denied; - }), - onError: (error, st) => debugPrint('$error')); + await _permissionHandler + .requestPermissions([permission]) + .then( + (status) => setState(() { + _permissionStatus = status[permission] ?? PermissionStatus.denied; + }), + onError: (error, st) => debugPrint('$error'), + ); } } diff --git a/permission_handler_html/lib/permission_handler_html.dart b/permission_handler_html/lib/permission_handler_html.dart index 8be2fa7c4..db6b28d37 100644 --- a/permission_handler_html/lib/permission_handler_html.dart +++ b/permission_handler_html/lib/permission_handler_html.dart @@ -33,22 +33,18 @@ class WebPermissionHandler extends PermissionHandlerPlatform { /// Registers the web plugin implementation. static void registerWith(Registrar registrar) { PermissionHandlerPlatform.instance = WebPermissionHandler( - webDelegate: WebDelegate( - _devices, - _geolocation, - _htmlPermissions, - ), + webDelegate: WebDelegate(_devices, _geolocation, _htmlPermissions), ); } /// Constructs a WebPermissionHandler. - WebPermissionHandler({ - required WebDelegate webDelegate, - }) : _webDelegate = webDelegate; + WebPermissionHandler({required WebDelegate webDelegate}) + : _webDelegate = webDelegate; @override Future> requestPermissions( - List permissions) async { + List permissions, + ) async { return _webDelegate.requestPermissions(permissions); } @@ -64,7 +60,8 @@ class WebPermissionHandler extends PermissionHandlerPlatform { @override Future shouldShowRequestPermissionRationale( - Permission permission) async { + Permission permission, + ) async { return SynchronousFuture(false); } diff --git a/permission_handler_html/lib/web_delegate.dart b/permission_handler_html/lib/web_delegate.dart index 1db991418..e9a381ece 100644 --- a/permission_handler_html/lib/web_delegate.dart +++ b/permission_handler_html/lib/web_delegate.dart @@ -13,9 +13,9 @@ class WebDelegate { web.MediaDevices? devices, web.Geolocation? geolocation, web.Permissions? permissions, - ) : _devices = devices, - _geolocation = geolocation, - _htmlPermissions = permissions; + ) : _devices = devices, + _geolocation = geolocation, + _htmlPermissions = permissions; /// The html media devices object used to request camera and microphone permissions. final web.MediaDevices? _devices; @@ -61,7 +61,9 @@ class WebDelegate { } Future _permissionStatusState( - String webPermissionName, web.Permissions? permissions) async { + String webPermissionName, + web.Permissions? permissions, + ) async { final webPermissionStatus = await permissions ?.query(_PermissionDescriptor(name: webPermissionName)) .toDart; @@ -129,9 +131,9 @@ class WebDelegate { } Future _requestNotificationPermission() async { - return web.Notification.requestPermission() - .toDart - .then((permission) => (permission == "granted".toJS)); + return web.Notification.requestPermission().toDart.then( + (permission) => (permission == "granted".toJS), + ); } Future _requestLocationPermission() async { @@ -152,14 +154,16 @@ class WebDelegate { } Future _requestSingularPermission( - Permission permission) async { + Permission permission, + ) async { bool permissionGranted = switch (permission) { Permission.microphone => await _requestMicrophonePermission(), Permission.camera => await _requestCameraPermission(), Permission.notification => await _requestNotificationPermission(), Permission.location => await _requestLocationPermission(), _ => throw UnsupportedError( - 'The ${permission.toString()} permission is currently not supported on web.') + 'The ${permission.toString()} permission is currently not supported on web.', + ), }; if (!permissionGranted) { @@ -173,13 +177,15 @@ class WebDelegate { /// /// Returns a [Map] containing the status per requested [Permission]. Future> requestPermissions( - List permissions) async { + List permissions, + ) async { final Map permissionStatusMap = {}; for (final permission in permissions) { try { - permissionStatusMap[permission] = - await _requestSingularPermission(permission); + permissionStatusMap[permission] = await _requestSingularPermission( + permission, + ); } on UnimplementedError { rethrow; } diff --git a/permission_handler_platform_interface/lib/src/method_channel/method_channel_permission_handler.dart b/permission_handler_platform_interface/lib/src/method_channel/method_channel_permission_handler.dart index 5f03e3e7a..ca11e55d0 100644 --- a/permission_handler_platform_interface/lib/src/method_channel/method_channel_permission_handler.dart +++ b/permission_handler_platform_interface/lib/src/method_channel/method_channel_permission_handler.dart @@ -6,8 +6,9 @@ import 'package:flutter/services.dart'; import '../../permission_handler_platform_interface.dart'; import 'utils/codec.dart'; -const MethodChannel _methodChannel = - MethodChannel('flutter.baseflow.com/permissions/methods'); +const MethodChannel _methodChannel = MethodChannel( + 'flutter.baseflow.com/permissions/methods', +); /// An implementation of [PermissionHandlerPlatform] that uses [MethodChannel]s. class MethodChannelPermissionHandler extends PermissionHandlerPlatform { @@ -15,7 +16,9 @@ class MethodChannelPermissionHandler extends PermissionHandlerPlatform { @override Future checkPermissionStatus(Permission permission) async { final status = await _methodChannel.invokeMethod( - 'checkPermissionStatus', permission.value); + 'checkPermissionStatus', + permission.value, + ); return decodePermissionStatus(status); } @@ -52,7 +55,9 @@ class MethodChannelPermissionHandler extends PermissionHandlerPlatform { @override Future checkServiceStatus(Permission permission) async { final status = await _methodChannel.invokeMethod( - 'checkServiceStatus', permission.value); + 'checkServiceStatus', + permission.value, + ); return decodeServiceStatus(status); } @@ -74,10 +79,13 @@ class MethodChannelPermissionHandler extends PermissionHandlerPlatform { /// Returns a [Map] containing the status per requested [Permission]. @override Future> requestPermissions( - List permissions) async { + List permissions, + ) async { final data = encodePermissions(permissions); - final status = - await _methodChannel.invokeMethod('requestPermissions', data); + final status = await _methodChannel.invokeMethod( + 'requestPermissions', + data, + ); return decodePermissionRequestResult(Map.from(status)); } @@ -88,13 +96,16 @@ class MethodChannelPermissionHandler extends PermissionHandlerPlatform { /// returns [false]. @override Future shouldShowRequestPermissionRationale( - Permission permission) async { + Permission permission, + ) async { if (defaultTargetPlatform != TargetPlatform.android) { return false; } final shouldShowRationale = await _methodChannel.invokeMethod( - 'shouldShowRequestPermissionRationale', permission.value); + 'shouldShowRequestPermissionRationale', + permission.value, + ); return shouldShowRationale ?? false; } diff --git a/permission_handler_platform_interface/lib/src/method_channel/utils/codec.dart b/permission_handler_platform_interface/lib/src/method_channel/utils/codec.dart index dc5db075c..99bd0768a 100644 --- a/permission_handler_platform_interface/lib/src/method_channel/utils/codec.dart +++ b/permission_handler_platform_interface/lib/src/method_channel/utils/codec.dart @@ -13,9 +13,14 @@ ServiceStatus decodeServiceStatus(int value) { /// Converts the given [Map] of [int]s into a [Map] with [Permission]s as /// keys and their respective [PermissionStatus] as value. Map decodePermissionRequestResult( - Map value) { - return value.map((key, value) => MapEntry( - Permission.byValue(key), PermissionStatusValue.statusByValue(value))); + Map value, +) { + return value.map( + (key, value) => MapEntry( + Permission.byValue(key), + PermissionStatusValue.statusByValue(value), + ), + ); } /// Converts the given [List] of [Permission]s into a [List] of [int]s which diff --git a/permission_handler_platform_interface/lib/src/permission_handler_platform_interface.dart b/permission_handler_platform_interface/lib/src/permission_handler_platform_interface.dart index 32cb2b722..24685265e 100644 --- a/permission_handler_platform_interface/lib/src/permission_handler_platform_interface.dart +++ b/permission_handler_platform_interface/lib/src/permission_handler_platform_interface.dart @@ -32,7 +32,8 @@ abstract class PermissionHandlerPlatform extends PlatformInterface { /// Checks the current status of the given [Permission]. Future checkPermissionStatus(Permission permission) { throw UnimplementedError( - 'checkPermissionStatus() has not been implemented.'); + 'checkPermissionStatus() has not been implemented.', + ); } /// Checks the current status of the service associated with the given @@ -73,7 +74,8 @@ abstract class PermissionHandlerPlatform extends PlatformInterface { /// /// Returns a [Map] containing the status per requested [Permission]. Future> requestPermissions( - List permissions) { + List permissions, + ) { throw UnimplementedError('requestPermissions() has not been implemented.'); } @@ -83,6 +85,7 @@ abstract class PermissionHandlerPlatform extends PlatformInterface { /// returns [false]. Future shouldShowRequestPermissionRationale(Permission permission) { throw UnimplementedError( - 'shouldShowRequestPermissionRationale() has not been implemented.'); + 'shouldShowRequestPermissionRationale() has not been implemented.', + ); } } diff --git a/permission_handler_platform_interface/test/src/method_channel/method_channel_mock.dart b/permission_handler_platform_interface/test/src/method_channel/method_channel_mock.dart index 2b5da964a..77e4671f4 100644 --- a/permission_handler_platform_interface/test/src/method_channel/method_channel_mock.dart +++ b/permission_handler_platform_interface/test/src/method_channel/method_channel_mock.dart @@ -19,8 +19,10 @@ class MethodChannelMock { Future _handler(MethodCall methodCall) async { if (methodCall.method != method) { - throw MissingPluginException('No implementation found for method ' - '$method on channel ${methodChannel.name}'); + throw MissingPluginException( + 'No implementation found for method ' + '$method on channel ${methodChannel.name}', + ); } return Future.delayed(delay, () { diff --git a/permission_handler_platform_interface/test/src/method_channel/method_channel_permission_handler_test.dart b/permission_handler_platform_interface/test/src/method_channel/method_channel_permission_handler_test.dart index c03c279a1..67def69d1 100644 --- a/permission_handler_platform_interface/test/src/method_channel/method_channel_permission_handler_test.dart +++ b/permission_handler_platform_interface/test/src/method_channel/method_channel_permission_handler_test.dart @@ -4,10 +4,10 @@ import 'package:permission_handler_platform_interface/src/method_channel/method_ import 'method_channel_mock.dart'; List get mockPermissions => List.of({ - Permission.contacts, - Permission.camera, - Permission.calendarWriteOnly, - }); + Permission.contacts, + Permission.camera, + Permission.calendarWriteOnly, +}); Map get mockPermissionMap => {}; @@ -15,129 +15,140 @@ void main() { TestWidgetsFlutterBinding.ensureInitialized(); group('checkPermissionStatus: When checking for permission', () { - test('Should receive granted if user wants access to the requested feature', - () async { - MethodChannelMock( - channelName: 'flutter.baseflow.com/permissions/methods', - method: 'checkPermissionStatus', - result: PermissionStatus.denied.value, - ); - - final permissionStatus = await MethodChannelPermissionHandler() - .checkPermissionStatus(Permission.contacts); - - expect(permissionStatus, PermissionStatus.denied); - }); - - test('Should receive denied if user denied access to the requested feature', - () async { - MethodChannelMock( - channelName: 'flutter.baseflow.com/permissions/methods', - method: 'checkPermissionStatus', - result: PermissionStatus.denied.value, - ); - - final permissionStatus = await MethodChannelPermissionHandler() - .checkPermissionStatus(Permission.contacts); - - expect(permissionStatus, PermissionStatus.denied); - }); - test( - // ignore: lines_longer_than_80_chars - 'Should receive restricted if OS denied rights for to the requested feature', - () async { - MethodChannelMock( - channelName: 'flutter.baseflow.com/permissions/methods', - method: 'checkPermissionStatus', - result: PermissionStatus.restricted.value, - ); + 'Should receive granted if user wants access to the requested feature', + () async { + MethodChannelMock( + channelName: 'flutter.baseflow.com/permissions/methods', + method: 'checkPermissionStatus', + result: PermissionStatus.denied.value, + ); - final permissionStatus = await MethodChannelPermissionHandler() - .checkPermissionStatus(Permission.contacts); + final permissionStatus = await MethodChannelPermissionHandler() + .checkPermissionStatus(Permission.contacts); - expect(permissionStatus, PermissionStatus.restricted); - }); + expect(permissionStatus, PermissionStatus.denied); + }, + ); test( - // ignore: lines_longer_than_80_chars - 'Should receive limited if user has authorized this application for limited access', - () async { - MethodChannelMock( - channelName: 'flutter.baseflow.com/permissions/methods', - method: 'checkPermissionStatus', - result: PermissionStatus.limited.value, - ); + 'Should receive denied if user denied access to the requested feature', + () async { + MethodChannelMock( + channelName: 'flutter.baseflow.com/permissions/methods', + method: 'checkPermissionStatus', + result: PermissionStatus.denied.value, + ); - final permissionStatus = await MethodChannelPermissionHandler() - .checkPermissionStatus(Permission.contacts); + final permissionStatus = await MethodChannelPermissionHandler() + .checkPermissionStatus(Permission.contacts); - expect(permissionStatus, PermissionStatus.limited); - }); + expect(permissionStatus, PermissionStatus.denied); + }, + ); test( - // ignore: lines_longer_than_80_chars - 'Should receive permanentlyDenied if user denied access and selected to never show a request for this permission again', - () async { - MethodChannelMock( - channelName: 'flutter.baseflow.com/permissions/methods', - method: 'checkPermissionStatus', - result: PermissionStatus.permanentlyDenied.value, - ); + // ignore: lines_longer_than_80_chars + 'Should receive restricted if OS denied rights for to the requested feature', + () async { + MethodChannelMock( + channelName: 'flutter.baseflow.com/permissions/methods', + method: 'checkPermissionStatus', + result: PermissionStatus.restricted.value, + ); + + final permissionStatus = await MethodChannelPermissionHandler() + .checkPermissionStatus(Permission.contacts); + + expect(permissionStatus, PermissionStatus.restricted); + }, + ); - final permissionStatus = await MethodChannelPermissionHandler() - .checkPermissionStatus(Permission.contacts); + test( + // ignore: lines_longer_than_80_chars + 'Should receive limited if user has authorized this application for limited access', + () async { + MethodChannelMock( + channelName: 'flutter.baseflow.com/permissions/methods', + method: 'checkPermissionStatus', + result: PermissionStatus.limited.value, + ); + + final permissionStatus = await MethodChannelPermissionHandler() + .checkPermissionStatus(Permission.contacts); + + expect(permissionStatus, PermissionStatus.limited); + }, + ); - expect(permissionStatus, PermissionStatus.permanentlyDenied); - }); + test( + // ignore: lines_longer_than_80_chars + 'Should receive permanentlyDenied if user denied access and selected to never show a request for this permission again', + () async { + MethodChannelMock( + channelName: 'flutter.baseflow.com/permissions/methods', + method: 'checkPermissionStatus', + result: PermissionStatus.permanentlyDenied.value, + ); + + final permissionStatus = await MethodChannelPermissionHandler() + .checkPermissionStatus(Permission.contacts); + + expect(permissionStatus, PermissionStatus.permanentlyDenied); + }, + ); }); group('checkServiceStatus: When checking for service', () { // ignore: lines_longer_than_80_chars test( - 'Should receive disabled if the service for the permission is disabled', - () async { - MethodChannelMock( - channelName: 'flutter.baseflow.com/permissions/methods', - method: 'checkServiceStatus', - result: ServiceStatus.disabled.value, - ); + 'Should receive disabled if the service for the permission is disabled', + () async { + MethodChannelMock( + channelName: 'flutter.baseflow.com/permissions/methods', + method: 'checkServiceStatus', + result: ServiceStatus.disabled.value, + ); - final serviceStatus = await MethodChannelPermissionHandler() - .checkServiceStatus(Permission.contacts); + final serviceStatus = await MethodChannelPermissionHandler() + .checkServiceStatus(Permission.contacts); - expect(serviceStatus, ServiceStatus.disabled); - }); + expect(serviceStatus, ServiceStatus.disabled); + }, + ); - test('Should receive enabled if the service for the permission is enabled', - () async { - MethodChannelMock( - channelName: 'flutter.baseflow.com/permissions/methods', - method: 'checkServiceStatus', - result: ServiceStatus.enabled.value, - ); + test( + 'Should receive enabled if the service for the permission is enabled', + () async { + MethodChannelMock( + channelName: 'flutter.baseflow.com/permissions/methods', + method: 'checkServiceStatus', + result: ServiceStatus.enabled.value, + ); - final serviceStatus = await MethodChannelPermissionHandler() - .checkServiceStatus(Permission.contacts); + final serviceStatus = await MethodChannelPermissionHandler() + .checkServiceStatus(Permission.contacts); - expect(serviceStatus, ServiceStatus.enabled); - }); + expect(serviceStatus, ServiceStatus.enabled); + }, + ); test( - // ignore: lines_longer_than_80_chars - 'Should receive notApplicable if the permission does not have an associated service on the current platform', - () async { - MethodChannelMock( - channelName: 'flutter.baseflow.com/permissions/methods', - method: 'checkServiceStatus', - result: ServiceStatus.notApplicable.value, - ); - - final serviceStatus = await MethodChannelPermissionHandler() - .checkServiceStatus(Permission.contacts); - - expect(serviceStatus, ServiceStatus.notApplicable); - }); + // ignore: lines_longer_than_80_chars + 'Should receive notApplicable if the permission does not have an associated service on the current platform', + () async { + MethodChannelMock( + channelName: 'flutter.baseflow.com/permissions/methods', + method: 'checkServiceStatus', + result: ServiceStatus.notApplicable.value, + ); + + final serviceStatus = await MethodChannelPermissionHandler() + .checkServiceStatus(Permission.contacts); + + expect(serviceStatus, ServiceStatus.notApplicable); + }, + ); }); group('openAppSettings: When opening the App settings', () { @@ -148,8 +159,8 @@ void main() { result: true, ); - final hasOpenedAppSettings = - await MethodChannelPermissionHandler().openAppSettings(); + final hasOpenedAppSettings = await MethodChannelPermissionHandler() + .openAppSettings(); expect(hasOpenedAppSettings, true); }); @@ -161,8 +172,8 @@ void main() { result: false, ); - final hasOpenedAppSettings = - await MethodChannelPermissionHandler().openAppSettings(); + final hasOpenedAppSettings = await MethodChannelPermissionHandler() + .openAppSettings(); expect(hasOpenedAppSettings, false); }); @@ -170,36 +181,39 @@ void main() { group('requestPermissions: When requesting for permission', () { // ignore: lines_longer_than_80_chars - test('returns a Map with all the PermissionStatus of the given permissions', - () async { - MethodChannelMock( - channelName: 'flutter.baseflow.com/permissions/methods', - method: 'requestPermissions', - result: mockPermissionMap, - ); - - final result = await MethodChannelPermissionHandler() - .requestPermissions(mockPermissions); - - expect(result, isA>()); - }); + test( + 'returns a Map with all the PermissionStatus of the given permissions', + () async { + MethodChannelMock( + channelName: 'flutter.baseflow.com/permissions/methods', + method: 'requestPermissions', + result: mockPermissionMap, + ); + + final result = await MethodChannelPermissionHandler() + .requestPermissions(mockPermissions); + + expect(result, isA>()); + }, + ); }); group('shouldShowRequestPermissionRationale:', () { test( - // ignore: lines_longer_than_80_chars - 'should return true when you should show a rationale for requesting permission.', - () async { - MethodChannelMock( - channelName: 'flutter.baseflow.com/permissions/methods', - method: 'shouldShowRequestPermissionRationale', - result: true, - ); - - final shouldShowRationale = await MethodChannelPermissionHandler() - .shouldShowRequestPermissionRationale(mockPermissions.first); - - expect(shouldShowRationale, true); - }); + // ignore: lines_longer_than_80_chars + 'should return true when you should show a rationale for requesting permission.', + () async { + MethodChannelMock( + channelName: 'flutter.baseflow.com/permissions/methods', + method: 'shouldShowRequestPermissionRationale', + result: true, + ); + + final shouldShowRationale = await MethodChannelPermissionHandler() + .shouldShowRequestPermissionRationale(mockPermissions.first); + + expect(shouldShowRationale, true); + }, + ); }); } diff --git a/permission_handler_platform_interface/test/src/method_channel/utils/coded_test.dart b/permission_handler_platform_interface/test/src/method_channel/utils/coded_test.dart index 1742b9fc6..b9037c2b0 100644 --- a/permission_handler_platform_interface/test/src/method_channel/utils/coded_test.dart +++ b/permission_handler_platform_interface/test/src/method_channel/utils/coded_test.dart @@ -12,12 +12,9 @@ void main() { expect(decodeServiceStatus(0), ServiceStatus.disabled); }); - test( - 'decodePermissionRequestResult should convert a map' + test('decodePermissionRequestResult should convert a map' 'to map', () { - var value = { - 1: 1, - }; + var value = {1: 1}; var permissionMap = decodePermissionRequestResult(value); diff --git a/permission_handler_platform_interface/test/src/permission_handler_platform_interface_test.dart b/permission_handler_platform_interface/test/src/permission_handler_platform_interface_test.dart index c965e72ed..3977d648b 100644 --- a/permission_handler_platform_interface/test/src/permission_handler_platform_interface_test.dart +++ b/permission_handler_platform_interface/test/src/permission_handler_platform_interface_test.dart @@ -9,8 +9,10 @@ void main() { group('$PermissionHandlerPlatform', () { test('$MethodChannelPermissionHandler is the default instance', () { - expect(PermissionHandlerPlatform.instance, - isA()); + expect( + PermissionHandlerPlatform.instance, + isA(), + ); }); test('Cannot be implemented with `implements`', () { @@ -30,61 +32,71 @@ void main() { }); test( - // ignore: lines_longer_than_80_chars - 'Default implementation of checkPermissionStatus should throw unimplemented error', - () { - final permissionHandlerPlatform = ExtendsPermissionHandlerPlatform(); - - expect(() { - permissionHandlerPlatform - .checkPermissionStatus(Permission.accessMediaLocation); - }, throwsUnimplementedError); - }); + // ignore: lines_longer_than_80_chars + 'Default implementation of checkPermissionStatus should throw unimplemented error', + () { + final permissionHandlerPlatform = ExtendsPermissionHandlerPlatform(); + + expect(() { + permissionHandlerPlatform.checkPermissionStatus( + Permission.accessMediaLocation, + ); + }, throwsUnimplementedError); + }, + ); test( - // ignore: lines_longer_than_80_chars - 'Default implementation of checkServiceStatus should throw unimplemented error', - () { - final permissionHandlerPlatform = ExtendsPermissionHandlerPlatform(); - - expect(() { - permissionHandlerPlatform - .checkServiceStatus(Permission.accessMediaLocation); - }, throwsUnimplementedError); - }); + // ignore: lines_longer_than_80_chars + 'Default implementation of checkServiceStatus should throw unimplemented error', + () { + final permissionHandlerPlatform = ExtendsPermissionHandlerPlatform(); + + expect(() { + permissionHandlerPlatform.checkServiceStatus( + Permission.accessMediaLocation, + ); + }, throwsUnimplementedError); + }, + ); test( - // ignore: lines_longer_than_80_chars - 'Default implementation of openAppSettings should throw unimplemented error', - () { - final permissionHandlerPlatform = ExtendsPermissionHandlerPlatform(); - - expect( - permissionHandlerPlatform.openAppSettings, throwsUnimplementedError); - }); + // ignore: lines_longer_than_80_chars + 'Default implementation of openAppSettings should throw unimplemented error', + () { + final permissionHandlerPlatform = ExtendsPermissionHandlerPlatform(); + + expect( + permissionHandlerPlatform.openAppSettings, + throwsUnimplementedError, + ); + }, + ); test( - // ignore: lines_longer_than_80_chars - 'Default implementation of requestPermissions should throw unimplemented error', - () { - final permissionHandlerPlatform = ExtendsPermissionHandlerPlatform(); - var permission = [Permission.accessMediaLocation]; - - expect(() { - permissionHandlerPlatform.requestPermissions(permission); - }, throwsUnimplementedError); - }); + // ignore: lines_longer_than_80_chars + 'Default implementation of requestPermissions should throw unimplemented error', + () { + final permissionHandlerPlatform = ExtendsPermissionHandlerPlatform(); + var permission = [Permission.accessMediaLocation]; + + expect(() { + permissionHandlerPlatform.requestPermissions(permission); + }, throwsUnimplementedError); + }, + ); test( - // ignore: lines_longer_than_80_chars - 'Default implementation of shouldShowRequestPermissionRationale should throw unimplemented error', - () { - final permissionHandlerPlatform = ExtendsPermissionHandlerPlatform(); - expect(() { - permissionHandlerPlatform.shouldShowRequestPermissionRationale( - Permission.accessMediaLocation); - }, throwsUnimplementedError); - }); + // ignore: lines_longer_than_80_chars + 'Default implementation of shouldShowRequestPermissionRationale should throw unimplemented error', + () { + final permissionHandlerPlatform = ExtendsPermissionHandlerPlatform(); + expect(() { + permissionHandlerPlatform.shouldShowRequestPermissionRationale( + Permission.accessMediaLocation, + ); + }, throwsUnimplementedError); + }, + ); }); } @@ -99,5 +111,4 @@ class MockPermissionHandlerPlatform extends Mock with // ignore: prefer_mixin MockPlatformInterfaceMixin - implements - PermissionHandlerPlatform {} + implements PermissionHandlerPlatform {} diff --git a/permission_handler_platform_interface/test/src/permission_status_test.dart b/permission_handler_platform_interface/test/src/permission_status_test.dart index d26ee6b32..3e127754d 100644 --- a/permission_handler_platform_interface/test/src/permission_status_test.dart +++ b/permission_handler_platform_interface/test/src/permission_status_test.dart @@ -32,19 +32,32 @@ void main() { }); test( - // ignore: lines_longer_than_80_chars - 'statusByValue should return right index int that corresponds with the right PermissionStatus', - () { - expect(PermissionStatusValue.statusByValue(0), PermissionStatus.denied); - expect(PermissionStatusValue.statusByValue(1), PermissionStatus.granted); - expect( - PermissionStatusValue.statusByValue(2), PermissionStatus.restricted); - expect(PermissionStatusValue.statusByValue(3), PermissionStatus.limited); - expect(PermissionStatusValue.statusByValue(4), - PermissionStatus.permanentlyDenied); - expect( - PermissionStatusValue.statusByValue(5), PermissionStatus.provisional); - }); + // ignore: lines_longer_than_80_chars + 'statusByValue should return right index int that corresponds with the right PermissionStatus', + () { + expect(PermissionStatusValue.statusByValue(0), PermissionStatus.denied); + expect( + PermissionStatusValue.statusByValue(1), + PermissionStatus.granted, + ); + expect( + PermissionStatusValue.statusByValue(2), + PermissionStatus.restricted, + ); + expect( + PermissionStatusValue.statusByValue(3), + PermissionStatus.limited, + ); + expect( + PermissionStatusValue.statusByValue(4), + PermissionStatus.permanentlyDenied, + ); + expect( + PermissionStatusValue.statusByValue(5), + PermissionStatus.provisional, + ); + }, + ); }); group('PermissionStatusGetters', () { @@ -76,11 +89,15 @@ void main() { expect(await mockFuture(PermissionStatus.restricted).isRestricted, true); expect(await mockFuture(PermissionStatus.limited).isLimited, true); expect( - await mockFuture(PermissionStatus.permanentlyDenied) - .isPermanentlyDenied, - true); + await mockFuture( + PermissionStatus.permanentlyDenied, + ).isPermanentlyDenied, + true, + ); expect( - await mockFuture(PermissionStatus.provisional).isProvisional, true); + await mockFuture(PermissionStatus.provisional).isProvisional, + true, + ); }); test('Getters should return false if statement is not met', () async { @@ -89,7 +106,9 @@ void main() { expect(await mockFuture(PermissionStatus.restricted).isDenied, false); expect(await mockFuture(PermissionStatus.limited).isDenied, false); expect( - await mockFuture(PermissionStatus.permanentlyDenied).isDenied, false); + await mockFuture(PermissionStatus.permanentlyDenied).isDenied, + false, + ); expect(await mockFuture(PermissionStatus.provisional).isDenied, false); }); }); diff --git a/permission_handler_platform_interface/test/src/permissions_test.dart b/permission_handler_platform_interface/test/src/permissions_test.dart index 0f8beb470..2c388d807 100644 --- a/permission_handler_platform_interface/test/src/permissions_test.dart +++ b/permission_handler_platform_interface/test/src/permissions_test.dart @@ -32,47 +32,42 @@ void main() { }); test( - // ignore: lines_longer_than_80_chars - 'equality operator should return true for two instances with the same values', - () { - // Arrange - final firstPermission = Permission.byValue(1); - final secondPermission = Permission.byValue(1); + // ignore: lines_longer_than_80_chars + 'equality operator should return true for two instances with the same values', + () { + // Arrange + final firstPermission = Permission.byValue(1); + final secondPermission = Permission.byValue(1); - // Act & Assert - expect( - firstPermission == secondPermission, - true, - ); - }); + // Act & Assert + expect(firstPermission == secondPermission, true); + }, + ); test( - // ignore: lines_longer_than_80_chars - 'equality operator should return false for two instances with different values', - () { - // Arrange - final firstPermission = Permission.byValue(1); - final secondPermission = Permission.byValue(2); + // ignore: lines_longer_than_80_chars + 'equality operator should return false for two instances with different values', + () { + // Arrange + final firstPermission = Permission.byValue(1); + final secondPermission = Permission.byValue(2); - // Act & Assert - expect( - firstPermission == secondPermission, - false, - ); - }); + // Act & Assert + expect(firstPermission == secondPermission, false); + }, + ); - test('hashCode should be the same for two instances with the same values', - () { - // Arrange - final firstPermission = Permission.byValue(1); - final secondPermission = Permission.byValue(1); + test( + 'hashCode should be the same for two instances with the same values', + () { + // Arrange + final firstPermission = Permission.byValue(1); + final secondPermission = Permission.byValue(1); - // Act & Assert - expect( - firstPermission.hashCode, - secondPermission.hashCode, - ); - }); + // Act & Assert + expect(firstPermission.hashCode, secondPermission.hashCode); + }, + ); test('hashCode should not match for two instances with different values', () { // Arrange @@ -80,9 +75,6 @@ void main() { final secondPermission = Permission.byValue(2); // Act & Assert - expect( - firstPermission.hashCode == secondPermission.hashCode, - false, - ); + expect(firstPermission.hashCode == secondPermission.hashCode, false); }); } diff --git a/permission_handler_platform_interface/test/src/service_status_test.dart b/permission_handler_platform_interface/test/src/service_status_test.dart index b5db02424..6dad5489c 100644 --- a/permission_handler_platform_interface/test/src/service_status_test.dart +++ b/permission_handler_platform_interface/test/src/service_status_test.dart @@ -26,13 +26,17 @@ void main() { }); test( - // ignore: lines_longer_than_80_chars - 'statusByValue should return right index int that corresponds with the right PermissionStatus', - () { - expect(ServiceStatusValue.statusByValue(0), ServiceStatus.disabled); - expect(ServiceStatusValue.statusByValue(1), ServiceStatus.enabled); - expect(ServiceStatusValue.statusByValue(2), ServiceStatus.notApplicable); - }); + // ignore: lines_longer_than_80_chars + 'statusByValue should return right index int that corresponds with the right PermissionStatus', + () { + expect(ServiceStatusValue.statusByValue(0), ServiceStatus.disabled); + expect(ServiceStatusValue.statusByValue(1), ServiceStatus.enabled); + expect( + ServiceStatusValue.statusByValue(2), + ServiceStatus.notApplicable, + ); + }, + ); }); group('ServiceStatusGetters', () { diff --git a/permission_handler_windows/example/lib/main.dart b/permission_handler_windows/example/lib/main.dart index 58a4dc053..7c5a5522a 100644 --- a/permission_handler_windows/example/lib/main.dart +++ b/permission_handler_windows/example/lib/main.dart @@ -3,24 +3,30 @@ import 'package:flutter/material.dart'; import 'package:permission_handler_platform_interface/permission_handler_platform_interface.dart'; void main() { - runApp(BaseflowPluginExample( + runApp( + BaseflowPluginExample( pluginName: 'Permission Handler', githubURL: 'https://github.com/Baseflow/flutter-permission-handler', pubDevURL: 'https://pub.dev/packages/permission_handler', - pages: [PermissionHandlerWidget.createPage()])); + pages: [PermissionHandlerWidget.createPage()], + ), + ); } ///Defines the main theme color final MaterialColor themeMaterialColor = BaseflowPluginExample.createMaterialColor( - const Color.fromRGBO(48, 49, 60, 1)); + const Color.fromRGBO(48, 49, 60, 1), + ); /// A Flutter application demonstrating the functionality of this plugin class PermissionHandlerWidget extends StatefulWidget { /// Create a page containing the functionality of this plugin static ExamplePage createPage() { return ExamplePage( - Icons.location_on, (context) => PermissionHandlerWidget()); + Icons.location_on, + (context) => PermissionHandlerWidget(), + ); } @override @@ -33,18 +39,19 @@ class _PermissionHandlerWidgetState extends State { Widget build(BuildContext context) { return Center( child: ListView( - children: Permission.values - .where((permission) { - return permission != Permission.unknown && - permission != Permission.mediaLibrary && - permission != Permission.photos && - permission != Permission.photosAddOnly && - permission != Permission.reminders && - permission != Permission.appTrackingTransparency && - permission != Permission.criticalAlerts; - }) - .map((permission) => PermissionWidget(permission)) - .toList()), + children: Permission.values + .where((permission) { + return permission != Permission.unknown && + permission != Permission.mediaLibrary && + permission != Permission.photos && + permission != Permission.photosAddOnly && + permission != Permission.reminders && + permission != Permission.appTrackingTransparency && + permission != Permission.criticalAlerts; + }) + .map((permission) => PermissionWidget(permission)) + .toList(), + ), ); } } @@ -106,14 +113,14 @@ class _PermissionState extends State { ), trailing: (_permission is PermissionWithService) ? IconButton( - icon: const Icon( - Icons.info, - color: Colors.white, - ), + icon: const Icon(Icons.info, color: Colors.white), onPressed: () { checkServiceStatus( - context, _permission as PermissionWithService); - }) + context, + _permission as PermissionWithService, + ); + }, + ) : null, onTap: () { requestPermission(_permission); @@ -122,11 +129,16 @@ class _PermissionState extends State { } void checkServiceStatus( - BuildContext context, PermissionWithService permission) async { - ScaffoldMessenger.of(context).showSnackBar(SnackBar( - content: Text( - (await _permissionHandler.checkServiceStatus(permission)).toString()), - )); + BuildContext context, + PermissionWithService permission, + ) async { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text( + (await _permissionHandler.checkServiceStatus(permission)).toString(), + ), + ), + ); } Future requestPermission(Permission permission) async { From 68bfa3684ba137219e789ee81a884885f829114a Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 3 Jun 2026 12:05:24 +0200 Subject: [PATCH 42/57] Update to use monorepo for managing development --- .../Package.swift | 32 +++++++++++++++++++ .../FlutterGeneratedPluginSwiftPackage.swift | 3 ++ .../Flutter/ephemeral/flutter_lldb_helper.py | 32 +++++++++++++++++++ .../ios/Flutter/ephemeral/flutter_lldbinit | 5 +++ .../ephemeral/flutter_native_integration.env | 12 +++++++ permission_handler/example/pubspec.yaml | 4 ++- permission_handler/pubspec.yaml | 3 +- permission_handler_android/pubspec.yaml | 3 +- permission_handler_apple/pubspec.yaml | 7 ++-- permission_handler_html/pubspec.yaml | 7 ++-- .../pubspec.yaml | 3 +- permission_handler_windows/pubspec.yaml | 5 +-- pubspec.yaml | 13 ++++++++ 13 files changed, 117 insertions(+), 12 deletions(-) create mode 100644 permission_handler/example/ios/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage/Package.swift create mode 100644 permission_handler/example/ios/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage/Sources/FlutterGeneratedPluginSwiftPackage/FlutterGeneratedPluginSwiftPackage.swift create mode 100644 permission_handler/example/ios/Flutter/ephemeral/flutter_lldb_helper.py create mode 100644 permission_handler/example/ios/Flutter/ephemeral/flutter_lldbinit create mode 100644 permission_handler/example/ios/Flutter/ephemeral/flutter_native_integration.env create mode 100644 pubspec.yaml diff --git a/permission_handler/example/ios/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage/Package.swift b/permission_handler/example/ios/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage/Package.swift new file mode 100644 index 000000000..41fdeba8c --- /dev/null +++ b/permission_handler/example/ios/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage/Package.swift @@ -0,0 +1,32 @@ +// swift-tools-version: 5.9 +// The swift-tools-version declares the minimum version of Swift required to build this package. +// +// Generated file. Do not edit. +// + +import PackageDescription + +let package = Package( + name: "FlutterGeneratedPluginSwiftPackage", + platforms: [ + .iOS("13.0") + ], + products: [ + .library(name: "FlutterGeneratedPluginSwiftPackage", type: .static, targets: ["FlutterGeneratedPluginSwiftPackage"]) + ], + dependencies: [ + .package(name: "permission_handler_apple", path: "../.packages/permission_handler_apple"), + .package(name: "url_launcher_ios", path: "../.packages/url_launcher_ios-6.4.1"), + .package(name: "FlutterFramework", path: "../.packages/FlutterFramework") + ], + targets: [ + .target( + name: "FlutterGeneratedPluginSwiftPackage", + dependencies: [ + .product(name: "permission-handler-apple", package: "permission_handler_apple"), + .product(name: "url-launcher-ios", package: "url_launcher_ios"), + .product(name: "FlutterFramework", package: "FlutterFramework") + ] + ) + ] +) diff --git a/permission_handler/example/ios/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage/Sources/FlutterGeneratedPluginSwiftPackage/FlutterGeneratedPluginSwiftPackage.swift b/permission_handler/example/ios/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage/Sources/FlutterGeneratedPluginSwiftPackage/FlutterGeneratedPluginSwiftPackage.swift new file mode 100644 index 000000000..a30d95a81 --- /dev/null +++ b/permission_handler/example/ios/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage/Sources/FlutterGeneratedPluginSwiftPackage/FlutterGeneratedPluginSwiftPackage.swift @@ -0,0 +1,3 @@ +// +// Generated file. Do not edit. +// diff --git a/permission_handler/example/ios/Flutter/ephemeral/flutter_lldb_helper.py b/permission_handler/example/ios/Flutter/ephemeral/flutter_lldb_helper.py new file mode 100644 index 000000000..a88caf99d --- /dev/null +++ b/permission_handler/example/ios/Flutter/ephemeral/flutter_lldb_helper.py @@ -0,0 +1,32 @@ +# +# Generated file, do not edit. +# + +import lldb + +def handle_new_rx_page(frame: lldb.SBFrame, bp_loc, extra_args, intern_dict): + """Intercept NOTIFY_DEBUGGER_ABOUT_RX_PAGES and touch the pages.""" + base = frame.register["x0"].GetValueAsAddress() + page_len = frame.register["x1"].GetValueAsUnsigned() + + # Note: NOTIFY_DEBUGGER_ABOUT_RX_PAGES will check contents of the + # first page to see if handled it correctly. This makes diagnosing + # misconfiguration (e.g. missing breakpoint) easier. + data = bytearray(page_len) + data[0:8] = b'IHELPED!' + + error = lldb.SBError() + frame.GetThread().GetProcess().WriteMemory(base, data, error) + if not error.Success(): + print(f'Failed to write into {base}[+{page_len}]', error) + return + +def __lldb_init_module(debugger: lldb.SBDebugger, _): + target = debugger.GetDummyTarget() + # Caveat: must use BreakpointCreateByRegEx here and not + # BreakpointCreateByName. For some reasons callback function does not + # get carried over from dummy target for the later. + bp = target.BreakpointCreateByRegex("^NOTIFY_DEBUGGER_ABOUT_RX_PAGES$") + bp.SetScriptCallbackFunction('{}.handle_new_rx_page'.format(__name__)) + bp.SetAutoContinue(True) + print("-- LLDB integration loaded --") diff --git a/permission_handler/example/ios/Flutter/ephemeral/flutter_lldbinit b/permission_handler/example/ios/Flutter/ephemeral/flutter_lldbinit new file mode 100644 index 000000000..e3ba6fbed --- /dev/null +++ b/permission_handler/example/ios/Flutter/ephemeral/flutter_lldbinit @@ -0,0 +1,5 @@ +# +# Generated file, do not edit. +# + +command script import --relative-to-command-file flutter_lldb_helper.py diff --git a/permission_handler/example/ios/Flutter/ephemeral/flutter_native_integration.env b/permission_handler/example/ios/Flutter/ephemeral/flutter_native_integration.env new file mode 100644 index 000000000..89be47305 --- /dev/null +++ b/permission_handler/example/ios/Flutter/ephemeral/flutter_native_integration.env @@ -0,0 +1,12 @@ +FLUTTER_ROOT=/Users/au662726/fvm/versions/main +FLUTTER_APPLICATION_PATH=/Users/au662726/github_projects/flutter-permission-handler/permission_handler/example +FLUTTER_FRAMEWORK_SWIFT_PACKAGE_PATH=/Users/au662726/github_projects/flutter-permission-handler/permission_handler/example/ios/Flutter/ephemeral/Packages/.packages/FlutterFramework +COCOAPODS_PARALLEL_CODE_SIGN=true +FLUTTER_TARGET=lib/main.dart +FLUTTER_BUILD_DIR=build +FLUTTER_BUILD_NAME=1.0.0 +FLUTTER_BUILD_NUMBER=1 +DART_OBFUSCATION=false +TRACK_WIDGET_CREATION=true +TREE_SHAKE_ICONS=false +PACKAGE_CONFIG=.dart_tool/package_config.json diff --git a/permission_handler/example/pubspec.yaml b/permission_handler/example/pubspec.yaml index 8ea895146..c3627eebb 100644 --- a/permission_handler/example/pubspec.yaml +++ b/permission_handler/example/pubspec.yaml @@ -2,7 +2,9 @@ name: permission_handler_example description: Demonstrates how to use the permission_handler plugin. environment: - sdk: ^3.7.0 + sdk: ^3.6.0 + flutter: ">=3.24.0" +resolution: workspace dependencies: baseflow_plugin_template: ^2.1.1 diff --git a/permission_handler/pubspec.yaml b/permission_handler/pubspec.yaml index 7f8b93f42..d720f281c 100644 --- a/permission_handler/pubspec.yaml +++ b/permission_handler/pubspec.yaml @@ -5,8 +5,9 @@ issue_tracker: https://github.com/Baseflow/flutter-permission-handler/issues version: 13.0.1 environment: - sdk: ^3.5.0 + sdk: ^3.6.0 flutter: ">=3.24.0" +resolution: workspace flutter: plugin: diff --git a/permission_handler_android/pubspec.yaml b/permission_handler_android/pubspec.yaml index efd02930e..a60c3ed14 100644 --- a/permission_handler_android/pubspec.yaml +++ b/permission_handler_android/pubspec.yaml @@ -4,8 +4,9 @@ homepage: https://github.com/baseflow/flutter-permission-handler version: 14.0.1 environment: - sdk: ^3.5.0 + sdk: ^3.6.0 flutter: ">=3.24.0" +resolution: workspace flutter: plugin: diff --git a/permission_handler_apple/pubspec.yaml b/permission_handler_apple/pubspec.yaml index a03947478..d913c67b8 100644 --- a/permission_handler_apple/pubspec.yaml +++ b/permission_handler_apple/pubspec.yaml @@ -5,8 +5,9 @@ issue_tracker: https://github.com/Baseflow/flutter-permission-handler/issues version: 9.4.9 environment: - sdk: ">=2.18.0 <4.0.0" - flutter: ">=3.3.0" + sdk: ^3.6.0 + flutter: ">=3.24.0" +resolution: workspace flutter: plugin: @@ -21,5 +22,5 @@ dependencies: permission_handler_platform_interface: ^4.2.0 dev_dependencies: - flutter_lints: ^1.0.4 + flutter_lints: ^5.0.0 plugin_platform_interface: ^2.0.0 diff --git a/permission_handler_html/pubspec.yaml b/permission_handler_html/pubspec.yaml index 92d8fb40f..7af165520 100644 --- a/permission_handler_html/pubspec.yaml +++ b/permission_handler_html/pubspec.yaml @@ -5,8 +5,9 @@ version: 0.1.4+0 homepage: https://github.com/baseflow/flutter-permission-handler environment: - sdk: ">=3.3.0 <4.0.0" - flutter: ">=3.16.0" + sdk: ^3.5.0 + flutter: ">=3.24.0" +resolution: workspace dependencies: flutter: @@ -19,7 +20,7 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - flutter_lints: ^2.0.0 + flutter_lints: ^5.0.0 mockito: ^5.4.2 build_runner: ^2.1.2 test: ^1.24.4 diff --git a/permission_handler_platform_interface/pubspec.yaml b/permission_handler_platform_interface/pubspec.yaml index 665dac0b0..157c686d5 100644 --- a/permission_handler_platform_interface/pubspec.yaml +++ b/permission_handler_platform_interface/pubspec.yaml @@ -6,8 +6,9 @@ homepage: https://github.com/baseflow/flutter-permission-handler/tree/master/per version: 4.3.2 environment: - sdk: ^3.5.0 + sdk: ^3.6.0 flutter: ">=3.24.0" +resolution: workspace dependencies: flutter: diff --git a/permission_handler_windows/pubspec.yaml b/permission_handler_windows/pubspec.yaml index 3495a07b7..b01412999 100644 --- a/permission_handler_windows/pubspec.yaml +++ b/permission_handler_windows/pubspec.yaml @@ -21,5 +21,6 @@ dev_dependencies: plugin_platform_interface: ^2.0.0 environment: - sdk: ">=2.12.0 <4.0.0" - flutter: ">=2.0.0" + sdk: ^3.6.0 + flutter: ">=3.24.0" +resolution: workspace diff --git a/pubspec.yaml b/pubspec.yaml new file mode 100644 index 000000000..4a51ba2ae --- /dev/null +++ b/pubspec.yaml @@ -0,0 +1,13 @@ +name: _ +publish_to: none +environment: + sdk: ^3.6.0 + flutter: ">=3.24.0" +workspace: + - permission_handler + - permission_handler/example + - permission_handler_android + - permission_handler_apple + - permission_handler_html + - permission_handler_platform_interface + - permission_handler_windows From c3f5677459989645a64d13293e92a30a887f4311 Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 3 Jun 2026 12:33:53 +0200 Subject: [PATCH 43/57] Linting, formatting, fix analysis issues --- permission_handler/example/lib/main.dart | 4 +- permission_handler/example/pubspec.yaml | 1 + .../test/permission_handler_test.dart | 3 +- .../example/lib/main.dart | 52 +++++++------ .../example/pubspec.yaml | 11 +-- .../example/lib/main.dart | 76 ++++++++++--------- permission_handler_apple/example/pubspec.yaml | 14 ++-- permission_handler_html/example/lib/main.dart | 22 +++--- permission_handler_html/example/pubspec.yaml | 5 +- .../lib/permission_handler_html.dart | 2 +- permission_handler_html/lib/web_delegate.dart | 26 ++++--- ...ethod_channel_permission_handler_test.dart | 16 ++-- .../src/method_channel/utils/coded_test.dart | 3 +- ...ssion_handler_platform_interface_test.dart | 3 +- .../example/lib/main.dart | 44 +++++++---- .../example/pubspec.yaml | 62 +++++++-------- pubspec.yaml | 10 ++- 17 files changed, 187 insertions(+), 167 deletions(-) diff --git a/permission_handler/example/lib/main.dart b/permission_handler/example/lib/main.dart index 7a6ab62bc..9dbe35a1d 100644 --- a/permission_handler/example/lib/main.dart +++ b/permission_handler/example/lib/main.dart @@ -18,8 +18,8 @@ void main() { ///Defines the main theme color final MaterialColor themeMaterialColor = BaseflowPluginExample.createMaterialColor( - const Color.fromRGBO(48, 49, 60, 1), - ); + const Color.fromRGBO(48, 49, 60, 1), +); /// A Flutter application demonstrating the functionality of this plugin class PermissionHandlerWidget extends StatefulWidget { diff --git a/permission_handler/example/pubspec.yaml b/permission_handler/example/pubspec.yaml index c3627eebb..4b6545123 100644 --- a/permission_handler/example/pubspec.yaml +++ b/permission_handler/example/pubspec.yaml @@ -22,6 +22,7 @@ dev_dependencies: flutter_test: sdk: flutter url_launcher: ^6.3.1 + flutter_lints: ^5.0.0 flutter: uses-material-design: true diff --git a/permission_handler/test/permission_handler_test.dart b/permission_handler/test/permission_handler_test.dart index 4b51c142c..66ddfae12 100644 --- a/permission_handler/test/permission_handler_test.dart +++ b/permission_handler/test/permission_handler_test.dart @@ -178,7 +178,8 @@ class MockPermissionHandlerPlatform extends Mock with // ignore: prefer_mixin MockPlatformInterfaceMixin - implements PermissionHandlerPlatform { + implements + PermissionHandlerPlatform { @override Future checkPermissionStatus(Permission permission) => Future.value(PermissionStatus.granted); diff --git a/permission_handler_android/example/lib/main.dart b/permission_handler_android/example/lib/main.dart index f8f49b03d..4a0a6e052 100644 --- a/permission_handler_android/example/lib/main.dart +++ b/permission_handler_android/example/lib/main.dart @@ -42,20 +42,21 @@ class _PermissionHandlerWidgetState extends State { Widget build(BuildContext context) { return Center( child: ListView( - children: Permission.values - .where((permission) { - return permission != Permission.unknown && - permission != Permission.mediaLibrary && - permission != Permission.photosAddOnly && - permission != Permission.reminders && - permission != Permission.bluetooth && - permission != Permission.appTrackingTransparency && - permission != Permission.criticalAlerts && - permission != Permission.assistant && - permission != Permission.backgroundRefresh; - }) - .map((permission) => PermissionWidget(permission)) - .toList(), + children: + Permission.values + .where((permission) { + return permission != Permission.unknown && + permission != Permission.mediaLibrary && + permission != Permission.photosAddOnly && + permission != Permission.reminders && + permission != Permission.bluetooth && + permission != Permission.appTrackingTransparency && + permission != Permission.criticalAlerts && + permission != Permission.assistant && + permission != Permission.backgroundRefresh; + }) + .map((permission) => PermissionWidget(permission)) + .toList(), ), ); } @@ -117,17 +118,18 @@ class _PermissionState extends State { _permissionStatus.toString(), style: TextStyle(color: getPermissionColor()), ), - trailing: (widget._permission is PermissionWithService) - ? IconButton( - icon: const Icon(Icons.info, color: Colors.white), - onPressed: () { - checkServiceStatus( - context, - widget._permission as PermissionWithService, - ); - }, - ) - : null, + trailing: + (widget._permission is PermissionWithService) + ? IconButton( + icon: const Icon(Icons.info, color: Colors.white), + onPressed: () { + checkServiceStatus( + context, + widget._permission as PermissionWithService, + ); + }, + ) + : null, onTap: () { requestPermission(widget._permission); }, diff --git a/permission_handler_android/example/pubspec.yaml b/permission_handler_android/example/pubspec.yaml index e76011501..22839e1ae 100644 --- a/permission_handler_android/example/pubspec.yaml +++ b/permission_handler_android/example/pubspec.yaml @@ -3,6 +3,7 @@ description: Demonstrates how to use the permission_handler_android plugin. environment: sdk: ^3.7.0 +resolution: workspace dependencies: baseflow_plugin_template: ^2.1.2 @@ -13,14 +14,8 @@ dependencies: dev_dependencies: flutter_test: sdk: flutter - - permission_handler_android: - # When depending on this package from a real application you should use: - # permission_handler_android: ^x.y.z - # See https://dart.dev/tools/pub/dependencies#version-constraints - # The example app is bundled with the plugin so we use a path dependency on - # the parent directory to use the current plugin's version. - path: ../ + flutter_lints: ^5.0.0 + permission_handler_android: ^14.0.1 url_launcher: ^6.0.12 diff --git a/permission_handler_apple/example/lib/main.dart b/permission_handler_apple/example/lib/main.dart index 7605e3c48..ae9563d62 100644 --- a/permission_handler_apple/example/lib/main.dart +++ b/permission_handler_apple/example/lib/main.dart @@ -32,38 +32,39 @@ class PermissionHandlerWidget extends StatefulWidget { } @override - _PermissionHandlerWidgetState createState() => - _PermissionHandlerWidgetState(); + PermissionHandlerWidgetState createState() => PermissionHandlerWidgetState(); } -class _PermissionHandlerWidgetState extends State { +/// The state of the [PermissionHandlerWidget] that listens for permission status changes. +class PermissionHandlerWidgetState extends State { @override Widget build(BuildContext context) { return Center( child: ListView( - children: Permission.values - .where((permission) { - return permission != Permission.unknown && - permission != Permission.phone && - permission != Permission.sms && - permission != Permission.ignoreBatteryOptimizations && - permission != Permission.accessMediaLocation && - permission != Permission.activityRecognition && - permission != Permission.manageExternalStorage && - permission != Permission.systemAlertWindow && - permission != Permission.requestInstallPackages && - permission != Permission.accessNotificationPolicy && - permission != Permission.bluetoothScan && - permission != Permission.bluetoothAdvertise && - permission != Permission.bluetoothConnect && - permission != Permission.nearbyWifiDevices && - permission != Permission.videos && - permission != Permission.audio && - permission != Permission.scheduleExactAlarm && - permission != Permission.sensorsAlways; - }) - .map((permission) => PermissionWidget(permission)) - .toList(), + children: + Permission.values + .where((permission) { + return permission != Permission.unknown && + permission != Permission.phone && + permission != Permission.sms && + permission != Permission.ignoreBatteryOptimizations && + permission != Permission.accessMediaLocation && + permission != Permission.activityRecognition && + permission != Permission.manageExternalStorage && + permission != Permission.systemAlertWindow && + permission != Permission.requestInstallPackages && + permission != Permission.accessNotificationPolicy && + permission != Permission.bluetoothScan && + permission != Permission.bluetoothAdvertise && + permission != Permission.bluetoothConnect && + permission != Permission.nearbyWifiDevices && + permission != Permission.videos && + permission != Permission.audio && + permission != Permission.scheduleExactAlarm && + permission != Permission.sensorsAlways; + }) + .map((permission) => PermissionWidget(permission)) + .toList(), ), ); } @@ -124,17 +125,18 @@ class _PermissionState extends State { _permissionStatus.toString(), style: TextStyle(color: getPermissionColor()), ), - trailing: (widget.permission is PermissionWithService) - ? IconButton( - icon: const Icon(Icons.info, color: Colors.white), - onPressed: () { - checkServiceStatus( - context, - widget.permission as PermissionWithService, - ); - }, - ) - : null, + trailing: + (widget.permission is PermissionWithService) + ? IconButton( + icon: const Icon(Icons.info, color: Colors.white), + onPressed: () { + checkServiceStatus( + context, + widget.permission as PermissionWithService, + ); + }, + ) + : null, onTap: () { requestPermission(widget.permission); }, diff --git a/permission_handler_apple/example/pubspec.yaml b/permission_handler_apple/example/pubspec.yaml index 71aaacd79..042d6ae27 100644 --- a/permission_handler_apple/example/pubspec.yaml +++ b/permission_handler_apple/example/pubspec.yaml @@ -3,23 +3,21 @@ description: Demonstrates how to use the permission_handler_apple plugin. environment: sdk: ^3.7.0 + flutter: ">=3.24.0" dependencies: baseflow_plugin_template: ^2.1.1 + permission_handler_apple: ^9.4.9 + permission_handler_platform_interface: ^4.3.2 flutter: sdk: flutter +resolution: workspace + dev_dependencies: flutter_test: sdk: flutter - - permission_handler_apple: - # When depending on this package from a real application you should use: - # permission_handler: ^x.y.z - # See https://dart.dev/tools/pub/dependencies#version-constraints - # The example app is bundled with the plugin so we use a path dependency on - # the parent directory to use the current plugin's version. - path: ../ + flutter_lints: ^5.0.0 url_launcher: ^6.3.2 diff --git a/permission_handler_html/example/lib/main.dart b/permission_handler_html/example/lib/main.dart index 37ffcf5b3..3cc3d0b5b 100644 --- a/permission_handler_html/example/lib/main.dart +++ b/permission_handler_html/example/lib/main.dart @@ -16,8 +16,8 @@ void main() { ///Defines the main theme color final MaterialColor themeMaterialColor = BaseflowPluginExample.createMaterialColor( - const Color.fromRGBO(48, 49, 60, 1), - ); + const Color.fromRGBO(48, 49, 60, 1), +); /// A Flutter application demonstrating the functionality of this plugin class PermissionHandlerWidget extends StatefulWidget { @@ -85,9 +85,7 @@ class _PermissionState extends State { } void _listenForPermissionStatus() async { - await _permissionHandler - .checkPermissionStatus(widget._permission) - .then( + await _permissionHandler.checkPermissionStatus(widget._permission).then( (status) => setState(() => _permissionStatus = status), onError: (error, st) => debugPrint('$error'), ); @@ -148,13 +146,11 @@ class _PermissionState extends State { } Future requestPermission(Permission permission) async { - await _permissionHandler - .requestPermissions([permission]) - .then( - (status) => setState(() { - _permissionStatus = status[permission] ?? PermissionStatus.denied; - }), - onError: (error, st) => debugPrint('$error'), - ); + await _permissionHandler.requestPermissions([permission]).then( + (status) => setState(() { + _permissionStatus = status[permission] ?? PermissionStatus.denied; + }), + onError: (error, st) => debugPrint('$error'), + ); } } diff --git a/permission_handler_html/example/pubspec.yaml b/permission_handler_html/example/pubspec.yaml index f380c161a..122092b5b 100644 --- a/permission_handler_html/example/pubspec.yaml +++ b/permission_handler_html/example/pubspec.yaml @@ -2,8 +2,10 @@ name: permission_handler_html_example description: Demonstrates how to use the permission_handler_html plugin. environment: - sdk: ">=3.0.5 <4.0.0" + sdk: ^3.6.0 + flutter: ">=3.24.0" +resolution: workspace dependencies: permission_handler_platform_interface: ^4.2.0 baseflow_plugin_template: ^2.1.2 @@ -15,6 +17,7 @@ dev_dependencies: sdk: flutter flutter_test: sdk: flutter + flutter_lints: ^5.0.0 permission_handler_html: # When depending on this package from a real application you should use: diff --git a/permission_handler_html/lib/permission_handler_html.dart b/permission_handler_html/lib/permission_handler_html.dart index db6b28d37..05b8afa0a 100644 --- a/permission_handler_html/lib/permission_handler_html.dart +++ b/permission_handler_html/lib/permission_handler_html.dart @@ -39,7 +39,7 @@ class WebPermissionHandler extends PermissionHandlerPlatform { /// Constructs a WebPermissionHandler. WebPermissionHandler({required WebDelegate webDelegate}) - : _webDelegate = webDelegate; + : _webDelegate = webDelegate; @override Future> requestPermissions( diff --git a/permission_handler_html/lib/web_delegate.dart b/permission_handler_html/lib/web_delegate.dart index e9a381ece..0736ab310 100644 --- a/permission_handler_html/lib/web_delegate.dart +++ b/permission_handler_html/lib/web_delegate.dart @@ -13,9 +13,9 @@ class WebDelegate { web.MediaDevices? devices, web.Geolocation? geolocation, web.Permissions? permissions, - ) : _devices = devices, - _geolocation = geolocation, - _htmlPermissions = permissions; + ) : _devices = devices, + _geolocation = geolocation, + _htmlPermissions = permissions; /// The html media devices object used to request camera and microphone permissions. final web.MediaDevices? _devices; @@ -93,8 +93,10 @@ class WebDelegate { audioTracks[0].stop(); } } - } on web.DOMException { - return false; + } catch (e) { + if (e.isA()) { + return false; + } } return true; @@ -123,8 +125,10 @@ class WebDelegate { videoTracks[0].stop(); } } - } on web.DOMException { - return false; + } catch (e) { + if (e.isA()) { + return false; + } } return true; @@ -132,8 +136,8 @@ class WebDelegate { Future _requestNotificationPermission() async { return web.Notification.requestPermission().toDart.then( - (permission) => (permission == "granted".toJS), - ); + (permission) => (permission == "granted".toJS), + ); } Future _requestLocationPermission() async { @@ -162,8 +166,8 @@ class WebDelegate { Permission.notification => await _requestNotificationPermission(), Permission.location => await _requestLocationPermission(), _ => throw UnsupportedError( - 'The ${permission.toString()} permission is currently not supported on web.', - ), + 'The ${permission.toString()} permission is currently not supported on web.', + ), }; if (!permissionGranted) { diff --git a/permission_handler_platform_interface/test/src/method_channel/method_channel_permission_handler_test.dart b/permission_handler_platform_interface/test/src/method_channel/method_channel_permission_handler_test.dart index 67def69d1..b39410a65 100644 --- a/permission_handler_platform_interface/test/src/method_channel/method_channel_permission_handler_test.dart +++ b/permission_handler_platform_interface/test/src/method_channel/method_channel_permission_handler_test.dart @@ -4,10 +4,10 @@ import 'package:permission_handler_platform_interface/src/method_channel/method_ import 'method_channel_mock.dart'; List get mockPermissions => List.of({ - Permission.contacts, - Permission.camera, - Permission.calendarWriteOnly, -}); + Permission.contacts, + Permission.camera, + Permission.calendarWriteOnly, + }); Map get mockPermissionMap => {}; @@ -159,8 +159,8 @@ void main() { result: true, ); - final hasOpenedAppSettings = await MethodChannelPermissionHandler() - .openAppSettings(); + final hasOpenedAppSettings = + await MethodChannelPermissionHandler().openAppSettings(); expect(hasOpenedAppSettings, true); }); @@ -172,8 +172,8 @@ void main() { result: false, ); - final hasOpenedAppSettings = await MethodChannelPermissionHandler() - .openAppSettings(); + final hasOpenedAppSettings = + await MethodChannelPermissionHandler().openAppSettings(); expect(hasOpenedAppSettings, false); }); diff --git a/permission_handler_platform_interface/test/src/method_channel/utils/coded_test.dart b/permission_handler_platform_interface/test/src/method_channel/utils/coded_test.dart index b9037c2b0..2932a6406 100644 --- a/permission_handler_platform_interface/test/src/method_channel/utils/coded_test.dart +++ b/permission_handler_platform_interface/test/src/method_channel/utils/coded_test.dart @@ -12,7 +12,8 @@ void main() { expect(decodeServiceStatus(0), ServiceStatus.disabled); }); - test('decodePermissionRequestResult should convert a map' + test( + 'decodePermissionRequestResult should convert a map' 'to map', () { var value = {1: 1}; diff --git a/permission_handler_platform_interface/test/src/permission_handler_platform_interface_test.dart b/permission_handler_platform_interface/test/src/permission_handler_platform_interface_test.dart index 3977d648b..157602eef 100644 --- a/permission_handler_platform_interface/test/src/permission_handler_platform_interface_test.dart +++ b/permission_handler_platform_interface/test/src/permission_handler_platform_interface_test.dart @@ -111,4 +111,5 @@ class MockPermissionHandlerPlatform extends Mock with // ignore: prefer_mixin MockPlatformInterfaceMixin - implements PermissionHandlerPlatform {} + implements + PermissionHandlerPlatform {} diff --git a/permission_handler_windows/example/lib/main.dart b/permission_handler_windows/example/lib/main.dart index 7c5a5522a..4e5f30ca1 100644 --- a/permission_handler_windows/example/lib/main.dart +++ b/permission_handler_windows/example/lib/main.dart @@ -1,3 +1,5 @@ +// ignore_for_file: avoid_print + import 'package:baseflow_plugin_template/baseflow_plugin_template.dart'; import 'package:flutter/material.dart'; import 'package:permission_handler_platform_interface/permission_handler_platform_interface.dart'; @@ -16,11 +18,14 @@ void main() { ///Defines the main theme color final MaterialColor themeMaterialColor = BaseflowPluginExample.createMaterialColor( - const Color.fromRGBO(48, 49, 60, 1), - ); + const Color.fromRGBO(48, 49, 60, 1), +); /// A Flutter application demonstrating the functionality of this plugin class PermissionHandlerWidget extends StatefulWidget { + /// Creates a [PermissionHandlerWidget] that listens for permission status changes. + const PermissionHandlerWidget({super.key}); + /// Create a page containing the functionality of this plugin static ExamplePage createPage() { return ExamplePage( @@ -30,11 +35,11 @@ class PermissionHandlerWidget extends StatefulWidget { } @override - _PermissionHandlerWidgetState createState() => - _PermissionHandlerWidgetState(); + PermissionHandlerWidgetState createState() => PermissionHandlerWidgetState(); } -class _PermissionHandlerWidgetState extends State { +/// State for the [PermissionHandlerWidget] that listens for permission status changes. +class PermissionHandlerWidgetState extends State { @override Widget build(BuildContext context) { return Center( @@ -59,18 +64,21 @@ class _PermissionHandlerWidgetState extends State { /// Permission widget containing information about the passed [Permission] class PermissionWidget extends StatefulWidget { /// Constructs a [PermissionWidget] for the supplied [Permission] - const PermissionWidget(this._permission); + const PermissionWidget(this._permission, {super.key}); final Permission _permission; + /// Returns the [Permission] associated with this widget. + Permission get permission => _permission; + @override - _PermissionState createState() => _PermissionState(_permission); + PermissionWidgetState createState() => PermissionWidgetState(); } -class _PermissionState extends State { - _PermissionState(this._permission); - - final Permission _permission; +/// State for the [PermissionWidget] that listens for permission status changes. +class PermissionWidgetState extends State { + /// Constructs a [PermissionWidgetState] for the supplied [PermissionWidget]. + PermissionWidgetState(); final PermissionHandlerPlatform _permissionHandler = PermissionHandlerPlatform.instance; PermissionStatus _permissionStatus = PermissionStatus.denied; @@ -83,10 +91,12 @@ class _PermissionState extends State { } void _listenForPermissionStatus() async { - final status = await _permissionHandler.checkPermissionStatus(_permission); + final status = + await _permissionHandler.checkPermissionStatus(widget.permission); setState(() => _permissionStatus = status); } + /// Returns the color to use for the permission status. Color getPermissionColor() { switch (_permissionStatus) { case PermissionStatus.denied: @@ -104,30 +114,31 @@ class _PermissionState extends State { Widget build(BuildContext context) { return ListTile( title: Text( - _permission.toString(), + widget.permission.toString(), style: Theme.of(context).textTheme.bodyLarge, ), subtitle: Text( _permissionStatus.toString(), style: TextStyle(color: getPermissionColor()), ), - trailing: (_permission is PermissionWithService) + trailing: (widget.permission is PermissionWithService) ? IconButton( icon: const Icon(Icons.info, color: Colors.white), onPressed: () { checkServiceStatus( context, - _permission as PermissionWithService, + widget.permission as PermissionWithService, ); }, ) : null, onTap: () { - requestPermission(_permission); + requestPermission(widget.permission); }, ); } + /// Requests permission for the given [Permission]. void checkServiceStatus( BuildContext context, PermissionWithService permission, @@ -141,6 +152,7 @@ class _PermissionState extends State { ); } + /// Requests permission for the given [Permission]. Future requestPermission(Permission permission) async { final status = await _permissionHandler.requestPermissions([permission]); diff --git a/permission_handler_windows/example/pubspec.yaml b/permission_handler_windows/example/pubspec.yaml index 2deb8e72c..0c9e1d4f5 100644 --- a/permission_handler_windows/example/pubspec.yaml +++ b/permission_handler_windows/example/pubspec.yaml @@ -1,33 +1,29 @@ -name: permission_handler_windows_example -description: Demonstrates how to use the permission_handler_windows plugin. - -environment: - sdk: ">=2.15.0 <3.0.0" - -dependencies: - baseflow_plugin_template: ^2.1.1 - flutter: - sdk: flutter - -dev_dependencies: - flutter_test: - sdk: flutter - - permission_handler_windows: - # When depending on this package from a real application you should use: - # permission_handler_windows: ^x.y.z - # See https://dart.dev/tools/pub/dependencies#version-constraints - # The example app is bundled with the plugin so we use a path dependency on - # the parent directory to use the current plugin's version. - path: ../ - - url_launcher: ^6.0.12 - -flutter: - uses-material-design: true - - assets: - - res/images/baseflow_logo_def_light-02.png - - res/images/poweredByBaseflowLogoLight@3x.png - - packages/baseflow_plugin_template/logo.png - - packages/baseflow_plugin_template/poweredByBaseflow.png +name: permission_handler_windows_example +description: Demonstrates how to use the permission_handler_windows plugin. + +environment: + sdk: ^3.6.0 + flutter: ">=3.24.0" +resolution: workspace + +dependencies: + baseflow_plugin_template: ^2.1.1 + flutter: + sdk: flutter + permission_handler_windows: ^0.2.2 + permission_handler_platform_interface: ^4.1.0 + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^5.0.0 + url_launcher: ^6.0.12 + +flutter: + uses-material-design: true + + assets: + - res/images/baseflow_logo_def_light-02.png + - res/images/poweredByBaseflowLogoLight@3x.png + - packages/baseflow_plugin_template/logo.png + - packages/baseflow_plugin_template/poweredByBaseflow.png diff --git a/pubspec.yaml b/pubspec.yaml index 4a51ba2ae..56e2c0439 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,13 +1,21 @@ -name: _ +name: permission_handler_monorepo publish_to: none environment: sdk: ^3.6.0 flutter: ">=3.24.0" + workspace: - permission_handler - permission_handler/example - permission_handler_android + - permission_handler_android/example - permission_handler_apple + - permission_handler_apple/example - permission_handler_html + - permission_handler_html/example - permission_handler_platform_interface - permission_handler_windows + - permission_handler_windows/example + +dev_dependencies: + flutter_lints: ^5.0.0 From 5be8c066e8f967dd4a49c895e850b8c4aa2eeecd Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 3 Jun 2026 12:39:14 +0200 Subject: [PATCH 44/57] Fix test for number of permissions --- .../test/src/permissions_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/permission_handler_platform_interface/test/src/permissions_test.dart b/permission_handler_platform_interface/test/src/permissions_test.dart index 2c388d807..78160ddae 100644 --- a/permission_handler_platform_interface/test/src/permissions_test.dart +++ b/permission_handler_platform_interface/test/src/permissions_test.dart @@ -5,7 +5,7 @@ void main() { test('Permission has the right amount of possible Permission values', () { const values = Permission.values; - expect(values.length, 40); + expect(values.length, 41); }); test('check if byValue returns corresponding Permission value', () { From f67b8e9bf87e56214b74bfa03cb0fbcb21f09e4b Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 3 Jun 2026 12:43:08 +0200 Subject: [PATCH 45/57] Build after test (build is more time-costly) --- .github/workflows/permission_handler.yaml | 25 +++++++++++------------ 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/.github/workflows/permission_handler.yaml b/.github/workflows/permission_handler.yaml index 340849441..89a456d75 100644 --- a/.github/workflows/permission_handler.yaml +++ b/.github/workflows/permission_handler.yaml @@ -26,7 +26,7 @@ jobs: # TODO(mvanbeusekom): Manually set to macOS 15 to support Xcode 16 and iOS 18 SDKs. # Currently `macos-latest` is based on macOS 14 and doesn't support iOS 18 SDK. This # should be moved back to `macos-latest` when GitHub Actions images are updated. - runs-on: macos-15 + runs-on: macos-15 env: source-directory: ./permission_handler @@ -62,18 +62,7 @@ jobs: - name: Run Flutter Analyzer run: flutter analyze working-directory: ${{env.source-directory}} - - # Build Android version of the example App - - name: Run Android build - run: flutter build apk --release - working-directory: ${{env.example-directory}} - - # Build iOS version of the example App - - name: Run iOS build - run: flutter build ios --release --no-codesign - working-directory: ${{env.example-directory}} - - # Run all unit-tests with code coverage + # Run all unit-tests with code coverage - name: Run unit tests run: flutter test --coverage working-directory: ${{env.source-directory}} @@ -85,3 +74,13 @@ jobs: file: ${{env.source-directory}}/coverage/lcov.info # optional flags: unittests # optional name: permission_handler # optional + + # Build Android version of the example App + - name: Run Android build + run: flutter build apk --release + working-directory: ${{env.example-directory}} + + # Build iOS version of the example App + - name: Run iOS build + run: flutter build ios --release --no-codesign + working-directory: ${{env.example-directory}} From 684d96cf2e6cf582459853db5d2e6ecab325b67a Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 3 Jun 2026 12:45:00 +0200 Subject: [PATCH 46/57] Fix permission_handler android build compileSdk --- permission_handler/example/android/app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/permission_handler/example/android/app/build.gradle b/permission_handler/example/android/app/build.gradle index 047e56a5c..25715f826 100644 --- a/permission_handler/example/android/app/build.gradle +++ b/permission_handler/example/android/app/build.gradle @@ -25,7 +25,7 @@ android { if (project.android.hasProperty("namespace")) { namespace 'com.baseflow.permissionhandlerexample' } - compileSdkVersion 36 + compileSdkVersion 37 compileOptions { sourceCompatibility JavaVersion.VERSION_17 From 6bebe498dc61972f58db633787d27b3d0b52da5b Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 3 Jun 2026 12:50:01 +0200 Subject: [PATCH 47/57] Forgot to bump compilesdk version for android example app --- permission_handler_android/example/android/app/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/permission_handler_android/example/android/app/build.gradle b/permission_handler_android/example/android/app/build.gradle index 04ce10422..d740562c6 100644 --- a/permission_handler_android/example/android/app/build.gradle +++ b/permission_handler_android/example/android/app/build.gradle @@ -28,7 +28,7 @@ if (flutterVersionName == null) { android { namespace 'com.baseflow.permissionhandler.example' - compileSdkVersion 35 + compileSdkVersion 37 defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). From 33e4a18a2f322f643336d0f3eb085a996754cc4a Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 3 Jun 2026 13:02:41 +0200 Subject: [PATCH 48/57] update code coverage for permission_handler_platform_interface, add android 37 sdk --- .github/workflows/permission_handler.yaml | 5 ++++ .../workflows/permission_handler_android.yaml | 27 ++++++++++--------- ...permission_handler_platform_interface.yaml | 27 ++++++++++--------- 3 files changed, 34 insertions(+), 25 deletions(-) diff --git a/.github/workflows/permission_handler.yaml b/.github/workflows/permission_handler.yaml index 89a456d75..8b202d803 100644 --- a/.github/workflows/permission_handler.yaml +++ b/.github/workflows/permission_handler.yaml @@ -75,6 +75,11 @@ jobs: flags: unittests # optional name: permission_handler # optional + # Ensure that the android "platforms;android-37 is installed" + - name: Setup Android SDK + uses: android-actions/setup-android@v4 + with: + packages: "tools platform-tools platforms;android-37" # Build Android version of the example App - name: Run Android build run: flutter build apk --release diff --git a/.github/workflows/permission_handler_android.yaml b/.github/workflows/permission_handler_android.yaml index 0bbe16316..b7c403b1e 100644 --- a/.github/workflows/permission_handler_android.yaml +++ b/.github/workflows/permission_handler_android.yaml @@ -6,15 +6,15 @@ name: permission_handler_android # events but only for the main branch on: push: - branches: [ main ] + branches: [main] paths: - - 'permission_handler_android/**' - - '.github/workflows/permission_handler_android.yaml' + - "permission_handler_android/**" + - ".github/workflows/permission_handler_android.yaml" pull_request: - branches: [ main ] + branches: [main] paths: - - 'permission_handler_android/**' - - '.github/workflows/permission_handler_android.yaml' + - "permission_handler_android/**" + - ".github/workflows/permission_handler_android.yaml" # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: @@ -26,7 +26,7 @@ jobs: env: source-directory: ./permission_handler_android - example-directory: ./permission_handler_android/example + example-directory: ./permission_handler_android/example # Steps represent a sequence of tasks that will be executed as part of the job steps: @@ -36,13 +36,12 @@ jobs: # Make sure JAVA version 17 is installed on build agent. - uses: actions/setup-java@v3 with: - distribution: 'temurin' # See 'Supported distributions' for available options - java-version: '17' - + distribution: "temurin" # See 'Supported distributions' for available options + java-version: "17" # Make sure the stable version of Flutter is available - uses: subosito/flutter-action@v2 with: - channel: 'stable' + channel: "stable" # Download all Flutter packages - name: Download dependencies @@ -59,8 +58,12 @@ jobs: run: flutter analyze working-directory: ${{env.source-directory}} + # Ensure that the android "platforms;android-37 is installed" + - name: Setup Android SDK + uses: android-actions/setup-android@v4 + with: + packages: "tools platform-tools platforms;android-37" # Build Android version of the example App - name: Run Android build run: flutter build apk --release working-directory: ${{env.example-directory}} - \ No newline at end of file diff --git a/.github/workflows/permission_handler_platform_interface.yaml b/.github/workflows/permission_handler_platform_interface.yaml index 4f6408b78..46344a92b 100644 --- a/.github/workflows/permission_handler_platform_interface.yaml +++ b/.github/workflows/permission_handler_platform_interface.yaml @@ -6,15 +6,15 @@ name: permission_handler_platform_interface # events but only for the main branch on: push: - branches: [ main ] + branches: [main] paths: - - 'permission_handler_platform_interface/**' - - '.github/workflows/permission_handler_platform_interface.yaml' + - "permission_handler_platform_interface/**" + - ".github/workflows/permission_handler_platform_interface.yaml" pull_request: - branches: [ main ] + branches: [main] paths: - - 'permission_handler_platform_interface/**' - - '.github/workflows/permission_handler_platform_interface.yaml' + - "permission_handler_platform_interface/**" + - ".github/workflows/permission_handler_platform_interface.yaml" # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: @@ -25,17 +25,17 @@ jobs: runs-on: ubuntu-latest env: - source-directory: ./permission_handler_platform_interface + source-directory: ./permission_handler_platform_interface # Steps represent a sequence of tasks that will be executed as part of the job steps: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - uses: actions/checkout@v3 - + # Make sure the stable version of Flutter is available - uses: subosito/flutter-action@v2 with: - channel: 'stable' + channel: "stable" # Download all Flutter packages - name: Download dependencies @@ -46,20 +46,21 @@ jobs: - name: Run Dart Format run: dart format --set-exit-if-changed . working-directory: ${{env.source-directory}} - + # Run Flutter Analyzer - name: Run Flutter Analyzer run: flutter analyze working-directory: ${{env.source-directory}} - + # Run all unit-tests with code coverage - name: Run unit tests run: flutter test --coverage working-directory: ${{env.source-directory}} # Upload code coverage information - - uses: codecov/codecov-action@v1 + - uses: codecov/codecov-action@v3 with: + token: ${{ secrets.CODECOV_TOKEN }} file: ${{env.source-directory}}/coverage/lcov.info # optional name: permission_handler_platform_interface (Platform Interface Package) # optional - fail_ci_if_error: true \ No newline at end of file + flags: unittests From 62ceea6bf0ee2d2ff239e2523c90443c9688672b Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 3 Jun 2026 13:07:26 +0200 Subject: [PATCH 49/57] ...it is android 37.0, not android 37 --- .github/workflows/permission_handler.yaml | 2 +- .github/workflows/permission_handler_android.yaml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/permission_handler.yaml b/.github/workflows/permission_handler.yaml index 8b202d803..ce565c06c 100644 --- a/.github/workflows/permission_handler.yaml +++ b/.github/workflows/permission_handler.yaml @@ -79,7 +79,7 @@ jobs: - name: Setup Android SDK uses: android-actions/setup-android@v4 with: - packages: "tools platform-tools platforms;android-37" + packages: "tools platform-tools platforms;android-37.0" # Build Android version of the example App - name: Run Android build run: flutter build apk --release diff --git a/.github/workflows/permission_handler_android.yaml b/.github/workflows/permission_handler_android.yaml index b7c403b1e..1deaebd08 100644 --- a/.github/workflows/permission_handler_android.yaml +++ b/.github/workflows/permission_handler_android.yaml @@ -62,7 +62,7 @@ jobs: - name: Setup Android SDK uses: android-actions/setup-android@v4 with: - packages: "tools platform-tools platforms;android-37" + packages: "tools platform-tools platforms;android-37.0" # Build Android version of the example App - name: Run Android build run: flutter build apk --release From 8d432c2d0153be0949732b555e682e2b235a6f88 Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 3 Jun 2026 13:20:06 +0200 Subject: [PATCH 50/57] try to symlink the android-37.0 directory to android-37? --- .github/workflows/permission_handler.yaml | 19 +++++++++++++------ .../workflows/permission_handler_android.yaml | 19 ++++++++++++++----- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/.github/workflows/permission_handler.yaml b/.github/workflows/permission_handler.yaml index ce565c06c..9379808ab 100644 --- a/.github/workflows/permission_handler.yaml +++ b/.github/workflows/permission_handler.yaml @@ -42,7 +42,19 @@ jobs: with: distribution: "temurin" # See 'Supported distributions' for available options java-version: "17" - + # Ensure that the android "platforms;android-37 is installed" + - name: Setup Android SDK + uses: android-actions/setup-android@v4 + with: + packages: "tools platform-tools platforms;android-37.0" + # Symlink the android-37.0 to android-37 + - name: Symlink android-37.0 to android-37 + run: | + if [ -d "$ANDROID_HOME/platforms/android-37.0" ]; then + ln -s "$ANDROID_HOME/platforms/android-37.0" "$ANDROID_HOME/platforms/android-37" + else + echo "android-37.0 not found, skipping symlink" + fi # Make sure the stable version of Flutter is available - uses: subosito/flutter-action@v2 with: @@ -75,11 +87,6 @@ jobs: flags: unittests # optional name: permission_handler # optional - # Ensure that the android "platforms;android-37 is installed" - - name: Setup Android SDK - uses: android-actions/setup-android@v4 - with: - packages: "tools platform-tools platforms;android-37.0" # Build Android version of the example App - name: Run Android build run: flutter build apk --release diff --git a/.github/workflows/permission_handler_android.yaml b/.github/workflows/permission_handler_android.yaml index 1deaebd08..6a19784cd 100644 --- a/.github/workflows/permission_handler_android.yaml +++ b/.github/workflows/permission_handler_android.yaml @@ -38,6 +38,20 @@ jobs: with: distribution: "temurin" # See 'Supported distributions' for available options java-version: "17" + + # Ensure that the android "platforms;android-37 is installed" + - name: Setup Android SDK + uses: android-actions/setup-android@v4 + with: + packages: "tools platform-tools platforms;android-37.0" + # Symlink the android-37.0 to android-37 + - name: Symlink android-37.0 to android-37 + run: | + if [ -d "$ANDROID_HOME/platforms/android-37.0" ]; then + ln -s "$ANDROID_HOME/platforms/android-37.0" "$ANDROID_HOME/platforms/android-37" + else + echo "android-37.0 not found, skipping symlink" + fi # Make sure the stable version of Flutter is available - uses: subosito/flutter-action@v2 with: @@ -58,11 +72,6 @@ jobs: run: flutter analyze working-directory: ${{env.source-directory}} - # Ensure that the android "platforms;android-37 is installed" - - name: Setup Android SDK - uses: android-actions/setup-android@v4 - with: - packages: "tools platform-tools platforms;android-37.0" # Build Android version of the example App - name: Run Android build run: flutter build apk --release From 344f735c0754983c6b931ee9f05a7066ba071b0f Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 3 Jun 2026 13:28:59 +0200 Subject: [PATCH 51/57] ohhh...i think it is flutter. --- .github/workflows/permission_handler.yaml | 15 +-------------- .../workflows/permission_handler_android.yaml | 16 +--------------- 2 files changed, 2 insertions(+), 29 deletions(-) diff --git a/.github/workflows/permission_handler.yaml b/.github/workflows/permission_handler.yaml index 9379808ab..b5015bb98 100644 --- a/.github/workflows/permission_handler.yaml +++ b/.github/workflows/permission_handler.yaml @@ -42,23 +42,10 @@ jobs: with: distribution: "temurin" # See 'Supported distributions' for available options java-version: "17" - # Ensure that the android "platforms;android-37 is installed" - - name: Setup Android SDK - uses: android-actions/setup-android@v4 - with: - packages: "tools platform-tools platforms;android-37.0" - # Symlink the android-37.0 to android-37 - - name: Symlink android-37.0 to android-37 - run: | - if [ -d "$ANDROID_HOME/platforms/android-37.0" ]; then - ln -s "$ANDROID_HOME/platforms/android-37.0" "$ANDROID_HOME/platforms/android-37" - else - echo "android-37.0 not found, skipping symlink" - fi # Make sure the stable version of Flutter is available - uses: subosito/flutter-action@v2 with: - channel: "stable" + channel: "beta" # Download all Flutter packages - name: Download dependencies diff --git a/.github/workflows/permission_handler_android.yaml b/.github/workflows/permission_handler_android.yaml index 6a19784cd..03cd8923c 100644 --- a/.github/workflows/permission_handler_android.yaml +++ b/.github/workflows/permission_handler_android.yaml @@ -38,24 +38,10 @@ jobs: with: distribution: "temurin" # See 'Supported distributions' for available options java-version: "17" - - # Ensure that the android "platforms;android-37 is installed" - - name: Setup Android SDK - uses: android-actions/setup-android@v4 - with: - packages: "tools platform-tools platforms;android-37.0" - # Symlink the android-37.0 to android-37 - - name: Symlink android-37.0 to android-37 - run: | - if [ -d "$ANDROID_HOME/platforms/android-37.0" ]; then - ln -s "$ANDROID_HOME/platforms/android-37.0" "$ANDROID_HOME/platforms/android-37" - else - echo "android-37.0 not found, skipping symlink" - fi # Make sure the stable version of Flutter is available - uses: subosito/flutter-action@v2 with: - channel: "stable" + channel: "beta" # Download all Flutter packages - name: Download dependencies From 10c2f2857836bc7eb2e7ca866b7276a1622049d3 Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 3 Jun 2026 14:20:56 +0200 Subject: [PATCH 52/57] yes, flutter, but also outdated kotlin / gradle, etc --- .github/workflows/permission_handler.yaml | 2 +- .../workflows/permission_handler_android.yaml | 2 +- .../example/android/app/build.gradle | 55 ----------------- .../example/android/app/build.gradle.kts | 45 ++++++++++++++ .../example/android/build.gradle | 18 ------ .../example/android/build.gradle.kts | 24 ++++++++ .../example/android/gradle.properties | 7 ++- .../gradle/wrapper/gradle-wrapper.properties | 2 +- .../example/android/settings.gradle | 24 -------- .../example/android/settings.gradle.kts | 26 ++++++++ .../example/android/app/build.gradle | 60 ++++++++----------- .../example/android/build.gradle | 30 ---------- .../example/android/build.gradle.kts | 24 ++++++++ .../example/android/gradle.properties | 7 ++- .../gradle/wrapper/gradle-wrapper.properties | 5 +- .../example/android/settings.gradle | 24 -------- .../example/android/settings.gradle.kts | 26 ++++++++ 17 files changed, 187 insertions(+), 194 deletions(-) delete mode 100644 permission_handler/example/android/app/build.gradle create mode 100644 permission_handler/example/android/app/build.gradle.kts delete mode 100644 permission_handler/example/android/build.gradle create mode 100644 permission_handler/example/android/build.gradle.kts delete mode 100644 permission_handler/example/android/settings.gradle create mode 100644 permission_handler/example/android/settings.gradle.kts delete mode 100644 permission_handler_android/example/android/build.gradle create mode 100644 permission_handler_android/example/android/build.gradle.kts delete mode 100644 permission_handler_android/example/android/settings.gradle create mode 100644 permission_handler_android/example/android/settings.gradle.kts diff --git a/.github/workflows/permission_handler.yaml b/.github/workflows/permission_handler.yaml index b5015bb98..99f138b23 100644 --- a/.github/workflows/permission_handler.yaml +++ b/.github/workflows/permission_handler.yaml @@ -45,7 +45,7 @@ jobs: # Make sure the stable version of Flutter is available - uses: subosito/flutter-action@v2 with: - channel: "beta" + channel: "stable" # Download all Flutter packages - name: Download dependencies diff --git a/.github/workflows/permission_handler_android.yaml b/.github/workflows/permission_handler_android.yaml index 03cd8923c..547ff265f 100644 --- a/.github/workflows/permission_handler_android.yaml +++ b/.github/workflows/permission_handler_android.yaml @@ -41,7 +41,7 @@ jobs: # Make sure the stable version of Flutter is available - uses: subosito/flutter-action@v2 with: - channel: "beta" + channel: "stable" # Download all Flutter packages - name: Download dependencies diff --git a/permission_handler/example/android/app/build.gradle b/permission_handler/example/android/app/build.gradle deleted file mode 100644 index 25715f826..000000000 --- a/permission_handler/example/android/app/build.gradle +++ /dev/null @@ -1,55 +0,0 @@ -plugins { - id "com.android.application" - id "dev.flutter.flutter-gradle-plugin" -} - -def localProperties = new Properties() -def localPropertiesFile = rootProject.file('local.properties') -if (localPropertiesFile.exists()) { - localPropertiesFile.withReader('UTF-8') { reader -> - localProperties.load(reader) - } -} - -def flutterVersionCode = localProperties.getProperty('flutter.versionCode') -if (flutterVersionCode == null) { - flutterVersionCode = '1' -} - -def flutterVersionName = localProperties.getProperty('flutter.versionName') -if (flutterVersionName == null) { - flutterVersionName = '1.0' -} - -android { - if (project.android.hasProperty("namespace")) { - namespace 'com.baseflow.permissionhandlerexample' - } - compileSdkVersion 37 - - compileOptions { - sourceCompatibility JavaVersion.VERSION_17 - targetCompatibility JavaVersion.VERSION_17 - } - - defaultConfig { - // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId "com.baseflow.permissionhandler.example" - minSdkVersion flutter.minSdkVersion - targetSdkVersion 34 - versionCode flutterVersionCode.toInteger() - versionName flutterVersionName - } - - buildTypes { - release { - // TODO: Add your own signing config for the release build. - // Signing with the debug keys for now, so `flutter run --release` works. - signingConfig signingConfigs.debug - } - } -} - -flutter { - source '../..' -} diff --git a/permission_handler/example/android/app/build.gradle.kts b/permission_handler/example/android/app/build.gradle.kts new file mode 100644 index 000000000..602003d43 --- /dev/null +++ b/permission_handler/example/android/app/build.gradle.kts @@ -0,0 +1,45 @@ +plugins { + id("com.android.application") + // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. + id("dev.flutter.flutter-gradle-plugin") +} + +android { + namespace = "com.baseflow.permissionhandler.example" + compileSdk = 37 + ndkVersion = flutter.ndkVersion + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + + defaultConfig { + // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). + applicationId = "com.baseflow.permissionhandler.example" + // You can update the following values to match your application needs. + // For more information, see: https://flutter.dev/to/review-gradle-config. + minSdk = flutter.minSdkVersion + targetSdk = 35 + versionCode = flutter.versionCode + versionName = flutter.versionName + } + + buildTypes { + release { + // TODO: Add your own signing config for the release build. + // Signing with the debug keys for now, so `flutter run --release` works. + signingConfig = signingConfigs.getByName("debug") + } + } +} + +kotlin { + compilerOptions { + jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 + } +} + +flutter { + source = "../.." +} diff --git a/permission_handler/example/android/build.gradle b/permission_handler/example/android/build.gradle deleted file mode 100644 index 8f31e8caf..000000000 --- a/permission_handler/example/android/build.gradle +++ /dev/null @@ -1,18 +0,0 @@ -allprojects { - repositories { - google() - mavenCentral() - } -} - -rootProject.buildDir = '../build' -subprojects { - project.buildDir = "${rootProject.buildDir}/${project.name}" -} -subprojects { - project.evaluationDependsOn(':app') -} - -tasks.register("clean", Delete) { - delete rootProject.buildDir -} \ No newline at end of file diff --git a/permission_handler/example/android/build.gradle.kts b/permission_handler/example/android/build.gradle.kts new file mode 100644 index 000000000..dbee657bb --- /dev/null +++ b/permission_handler/example/android/build.gradle.kts @@ -0,0 +1,24 @@ +allprojects { + repositories { + google() + mavenCentral() + } +} + +val newBuildDir: Directory = + rootProject.layout.buildDirectory + .dir("../../build") + .get() +rootProject.layout.buildDirectory.value(newBuildDir) + +subprojects { + val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name) + project.layout.buildDirectory.value(newSubprojectBuildDir) +} +subprojects { + project.evaluationDependsOn(":app") +} + +tasks.register("clean") { + delete(rootProject.layout.buildDirectory) +} diff --git a/permission_handler/example/android/gradle.properties b/permission_handler/example/android/gradle.properties index 94adc3a3f..d5da7278a 100644 --- a/permission_handler/example/android/gradle.properties +++ b/permission_handler/example/android/gradle.properties @@ -1,3 +1,6 @@ -org.gradle.jvmargs=-Xmx1536M +org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError android.useAndroidX=true -android.enableJetifier=true +# This builtInKotlin flag was added automatically by Flutter migrator +android.builtInKotlin=false +# This newDsl flag was added automatically by Flutter migrator +android.newDsl=false diff --git a/permission_handler/example/android/gradle/wrapper/gradle-wrapper.properties b/permission_handler/example/android/gradle/wrapper/gradle-wrapper.properties index 9162f1008..a97e89ca1 100644 --- a/permission_handler/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/permission_handler/example/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-all.zip diff --git a/permission_handler/example/android/settings.gradle b/permission_handler/example/android/settings.gradle deleted file mode 100644 index 8cbe490f3..000000000 --- a/permission_handler/example/android/settings.gradle +++ /dev/null @@ -1,24 +0,0 @@ -pluginManagement { - def flutterSdkPath = { - def properties = new Properties() - file("local.properties").withInputStream { properties.load(it) } - def flutterSdkPath = properties.getProperty("flutter.sdk") - assert flutterSdkPath != null, "flutter.sdk not set in local.properties" - return flutterSdkPath - }() - - includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") - - repositories { - google() - mavenCentral() - gradlePluginPortal() - } -} - -plugins { - id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "8.9.1" apply false -} - -include ":app" \ No newline at end of file diff --git a/permission_handler/example/android/settings.gradle.kts b/permission_handler/example/android/settings.gradle.kts new file mode 100644 index 000000000..c21f0c5b4 --- /dev/null +++ b/permission_handler/example/android/settings.gradle.kts @@ -0,0 +1,26 @@ +pluginManagement { + val flutterSdkPath = + run { + val properties = java.util.Properties() + file("local.properties").inputStream().use { properties.load(it) } + val flutterSdkPath = properties.getProperty("flutter.sdk") + require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" } + flutterSdkPath + } + + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") + + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} + +plugins { + id("dev.flutter.flutter-plugin-loader") version "1.0.0" + id("com.android.application") version "9.0.1" apply false + id("org.jetbrains.kotlin.android") version "2.3.20" apply false +} + +include(":app") diff --git a/permission_handler_android/example/android/app/build.gradle b/permission_handler_android/example/android/app/build.gradle index d740562c6..602003d43 100644 --- a/permission_handler_android/example/android/app/build.gradle +++ b/permission_handler_android/example/android/app/build.gradle @@ -1,53 +1,45 @@ plugins { - id "com.android.application" - id "dev.flutter.flutter-gradle-plugin" -} - -def localProperties = new Properties() -def localPropertiesFile = rootProject.file('local.properties') -if (localPropertiesFile.exists()) { - localPropertiesFile.withReader('UTF-8') { reader -> - localProperties.load(reader) - } -} - -def flutterRoot = localProperties.getProperty('flutter.sdk') -if (flutterRoot == null) { - throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.") -} - -def flutterVersionCode = localProperties.getProperty('flutter.versionCode') -if (flutterVersionCode == null) { - flutterVersionCode = '1' -} - -def flutterVersionName = localProperties.getProperty('flutter.versionName') -if (flutterVersionName == null) { - flutterVersionName = '1.0' + id("com.android.application") + // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. + id("dev.flutter.flutter-gradle-plugin") } android { - namespace 'com.baseflow.permissionhandler.example' - compileSdkVersion 37 + namespace = "com.baseflow.permissionhandler.example" + compileSdk = 37 + ndkVersion = flutter.ndkVersion + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } defaultConfig { // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html). - applicationId "com.baseflow.permissionhandler.example" - minSdkVersion flutter.minSdkVersion - targetSdkVersion 35 - versionCode flutterVersionCode.toInteger() - versionName flutterVersionName + applicationId = "com.baseflow.permissionhandler.example" + // You can update the following values to match your application needs. + // For more information, see: https://flutter.dev/to/review-gradle-config. + minSdk = flutter.minSdkVersion + targetSdk = 35 + versionCode = flutter.versionCode + versionName = flutter.versionName } buildTypes { release { // TODO: Add your own signing config for the release build. // Signing with the debug keys for now, so `flutter run --release` works. - signingConfig signingConfigs.debug + signingConfig = signingConfigs.getByName("debug") } } } +kotlin { + compilerOptions { + jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 + } +} + flutter { - source '../..' + source = "../.." } diff --git a/permission_handler_android/example/android/build.gradle b/permission_handler_android/example/android/build.gradle deleted file mode 100644 index 0ed2bee85..000000000 --- a/permission_handler_android/example/android/build.gradle +++ /dev/null @@ -1,30 +0,0 @@ -allprojects { - repositories { - google() - mavenCentral() - } -} - -rootProject.buildDir = '../build' -subprojects { - project.buildDir = "${rootProject.buildDir}/${project.name}" -} -subprojects { - project.evaluationDependsOn(':app') -} - -tasks.register("clean", Delete) { - delete rootProject.buildDir -} - -// Build the plugin project with warnings enabled. This is here rather than -// in the plugin itself to avoid breaking clients that have different -// warnings (e.g., deprecation warnings from a newer SDK than this project -// builds with). -gradle.projectsEvaluated { - project(":permission_handler_android") { - tasks.withType(JavaCompile) { - options.compilerArgs << "-Xlint:all" << "-Werror" - } - } -} diff --git a/permission_handler_android/example/android/build.gradle.kts b/permission_handler_android/example/android/build.gradle.kts new file mode 100644 index 000000000..dbee657bb --- /dev/null +++ b/permission_handler_android/example/android/build.gradle.kts @@ -0,0 +1,24 @@ +allprojects { + repositories { + google() + mavenCentral() + } +} + +val newBuildDir: Directory = + rootProject.layout.buildDirectory + .dir("../../build") + .get() +rootProject.layout.buildDirectory.value(newBuildDir) + +subprojects { + val newSubprojectBuildDir: Directory = newBuildDir.dir(project.name) + project.layout.buildDirectory.value(newSubprojectBuildDir) +} +subprojects { + project.evaluationDependsOn(":app") +} + +tasks.register("clean") { + delete(rootProject.layout.buildDirectory) +} diff --git a/permission_handler_android/example/android/gradle.properties b/permission_handler_android/example/android/gradle.properties index 598d13fee..d5da7278a 100644 --- a/permission_handler_android/example/android/gradle.properties +++ b/permission_handler_android/example/android/gradle.properties @@ -1,3 +1,6 @@ -org.gradle.jvmargs=-Xmx4G +org.gradle.jvmargs=-Xmx8G -XX:MaxMetaspaceSize=4G -XX:ReservedCodeCacheSize=512m -XX:+HeapDumpOnOutOfMemoryError android.useAndroidX=true -android.enableJetifier=true +# This builtInKotlin flag was added automatically by Flutter migrator +android.builtInKotlin=false +# This newDsl flag was added automatically by Flutter migrator +android.newDsl=false diff --git a/permission_handler_android/example/android/gradle/wrapper/gradle-wrapper.properties b/permission_handler_android/example/android/gradle/wrapper/gradle-wrapper.properties index db18181ac..2e1113280 100644 --- a/permission_handler_android/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/permission_handler_android/example/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ -#Fri Jun 23 08:50:38 CEST 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip +networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip diff --git a/permission_handler_android/example/android/settings.gradle b/permission_handler_android/example/android/settings.gradle deleted file mode 100644 index 56eb85cb1..000000000 --- a/permission_handler_android/example/android/settings.gradle +++ /dev/null @@ -1,24 +0,0 @@ -pluginManagement { - def flutterSdkPath = { - def properties = new Properties() - file("local.properties").withInputStream { properties.load(it) } - def flutterSdkPath = properties.getProperty("flutter.sdk") - assert flutterSdkPath != null, "flutter.sdk not set in local.properties" - return flutterSdkPath - }() - - includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") - - repositories { - google() - mavenCentral() - gradlePluginPortal() - } -} - -plugins { - id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "8.7.0" apply false -} - -include ":app" \ No newline at end of file diff --git a/permission_handler_android/example/android/settings.gradle.kts b/permission_handler_android/example/android/settings.gradle.kts new file mode 100644 index 000000000..c21f0c5b4 --- /dev/null +++ b/permission_handler_android/example/android/settings.gradle.kts @@ -0,0 +1,26 @@ +pluginManagement { + val flutterSdkPath = + run { + val properties = java.util.Properties() + file("local.properties").inputStream().use { properties.load(it) } + val flutterSdkPath = properties.getProperty("flutter.sdk") + require(flutterSdkPath != null) { "flutter.sdk not set in local.properties" } + flutterSdkPath + } + + includeBuild("$flutterSdkPath/packages/flutter_tools/gradle") + + repositories { + google() + mavenCentral() + gradlePluginPortal() + } +} + +plugins { + id("dev.flutter.flutter-plugin-loader") version "1.0.0" + id("com.android.application") version "9.0.1" apply false + id("org.jetbrains.kotlin.android") version "2.3.20" apply false +} + +include(":app") From 8ea510930894d8abaffd33fc54ae6a3984858b23 Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 3 Jun 2026 14:46:23 +0200 Subject: [PATCH 53/57] accidental extra case during merge --- .../java/com/baseflow/permissionhandler/PermissionUtils.java | 1 - 1 file changed, 1 deletion(-) diff --git a/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionUtils.java b/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionUtils.java index a210d9570..35cc35e2d 100644 --- a/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionUtils.java +++ b/permission_handler_android/android/src/main/java/com/baseflow/permissionhandler/PermissionUtils.java @@ -620,7 +620,6 @@ static List getManifestNames( break; case PermissionConstants.PERMISSION_GROUP_MEDIA_LIBRARY: case PermissionConstants.PERMISSION_GROUP_REMINDERS: - case PermissionConstants.PERMISSION_GROUP_ACCESS_LOCAL_NETWORK: case PermissionConstants.PERMISSION_GROUP_UNKNOWN: return null; } From 3cbd39b24e8b4c4cfd1052aa50957e1e84bbb5b5 Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 3 Jun 2026 14:57:38 +0200 Subject: [PATCH 54/57] updated gitignore for ios --- permission_handler_apple/ios/.gitignore | 54 +++++++++++++------------ 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/permission_handler_apple/ios/.gitignore b/permission_handler_apple/ios/.gitignore index 3ed647344..8a62ea716 100644 --- a/permission_handler_apple/ios/.gitignore +++ b/permission_handler_apple/ios/.gitignore @@ -3,38 +3,40 @@ .sconsign.dblite .svn/ -.DS_Store -*.swp -profile - -DerivedData/ -build/ -GeneratedPluginRegistrant.h -GeneratedPluginRegistrant.m - -.generated/ - -*.pbxuser +**/dgph *.mode1v3 *.mode2v3 +*.moved-aside +*.pbxuser *.perspectivev3 - -!default.pbxuser +**/*sync/ +.sconsign.dblite +.tags* +**/.vagrant/ +**/DerivedData/ +Icon? +**/Pods/ +**/.symlinks/ +profile +xcuserdata +**/.generated/ +Flutter/App.framework +Flutter/Flutter.framework +Flutter/Flutter.podspec +Flutter/Generated.xcconfig +Flutter/ephemeral/ +Flutter/app.flx +Flutter/app.zip +Flutter/flutter_assets/ +Flutter/flutter_export_environment.sh +ServiceDefinitions.json +Runner/GeneratedPluginRegistrant.* + +# Exceptions to above rules. !default.mode1v3 !default.mode2v3 +!default.pbxuser !default.perspectivev3 - -xcuserdata - -*.moved-aside - -*.pyc -*sync/ -Icon? -.tags* - -/Flutter/Generated.xcconfig - # Swift Package Manager .build/ *.resolved From a55678675325381a1546182ef6a7fc441babbcb4 Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 3 Jun 2026 15:06:49 +0200 Subject: [PATCH 55/57] Updated android plugin gradle / config --- .../android/build.gradle | 39 ---------- .../android/build.gradle.kts | 77 +++++++++++++++++++ .../gradle/wrapper/gradle-wrapper.properties | 2 +- .../{settings.gradle => settings.gradle.kts} | 0 .../app/{build.gradle => build.gradle.kts} | 0 5 files changed, 78 insertions(+), 40 deletions(-) delete mode 100644 permission_handler_android/android/build.gradle create mode 100644 permission_handler_android/android/build.gradle.kts rename permission_handler_android/android/{settings.gradle => settings.gradle.kts} (100%) rename permission_handler_android/example/android/app/{build.gradle => build.gradle.kts} (100%) diff --git a/permission_handler_android/android/build.gradle b/permission_handler_android/android/build.gradle deleted file mode 100644 index 443882c1f..000000000 --- a/permission_handler_android/android/build.gradle +++ /dev/null @@ -1,39 +0,0 @@ -group 'com.baseflow.permissionhandler' -version '1.0' - -buildscript { - repositories { - google() - mavenCentral() - } - - dependencies { - classpath 'com.android.tools.build:gradle:8.0.2' - } -} - -rootProject.allprojects { - repositories { - google() - mavenCentral() - } -} - -apply plugin: 'com.android.library' - -android { - // Conditional for compatibility with AGP <4.2. - if (project.android.hasProperty("namespace")) { - namespace 'com.baseflow.permissionhandler' - } - compileSdkVersion 37 - - compileOptions { - sourceCompatibility JavaVersion.VERSION_17 - targetCompatibility JavaVersion.VERSION_17 - } - - defaultConfig { - minSdkVersion 19 - } -} diff --git a/permission_handler_android/android/build.gradle.kts b/permission_handler_android/android/build.gradle.kts new file mode 100644 index 000000000..da4d8033d --- /dev/null +++ b/permission_handler_android/android/build.gradle.kts @@ -0,0 +1,77 @@ +group = "com.baseflow.permissionhandler" +version = "1.0" + +buildscript { + val kotlinVersion = "2.3.20" + repositories { + google() + mavenCentral() + } + + dependencies { + classpath("com.android.tools.build:gradle:9.0.1") + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion") + } +} + +allprojects { + repositories { + google() + mavenCentral() + } +} + +plugins { + id("com.android.library") +} + +android { + namespace = "com.baseflow.permissionhandler" + + compileSdk = 37 + + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + + sourceSets { + getByName("main") { + java.srcDirs("src/main/kotlin") + } + getByName("test") { + java.srcDirs("src/test/kotlin") + } + } + + defaultConfig { + minSdk = 24 + } + + testOptions { + unitTests { + isIncludeAndroidResources = true + all { + it.useJUnitPlatform() + + it.outputs.upToDateWhen { false } + + it.testLogging { + events("passed", "skipped", "failed", "standardOut", "standardError") + showStandardStreams = true + } + } + } + } +} + +kotlin { + compilerOptions { + jvmTarget = org.jetbrains.kotlin.gradle.dsl.JvmTarget.JVM_17 + } +} + +dependencies { + testImplementation("org.jetbrains.kotlin:kotlin-test") + testImplementation("org.mockito:mockito-core:5.0.0") +} diff --git a/permission_handler_android/android/gradle/wrapper/gradle-wrapper.properties b/permission_handler_android/android/gradle/wrapper/gradle-wrapper.properties index da9702f9e..d706aba60 100644 --- a/permission_handler_android/android/gradle/wrapper/gradle-wrapper.properties +++ b/permission_handler_android/android/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.8-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-9.1.0-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/permission_handler_android/android/settings.gradle b/permission_handler_android/android/settings.gradle.kts similarity index 100% rename from permission_handler_android/android/settings.gradle rename to permission_handler_android/android/settings.gradle.kts diff --git a/permission_handler_android/example/android/app/build.gradle b/permission_handler_android/example/android/app/build.gradle.kts similarity index 100% rename from permission_handler_android/example/android/app/build.gradle rename to permission_handler_android/example/android/app/build.gradle.kts From 8a40c212eb31cd18cef58ff2f065366f4068beba Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 3 Jun 2026 15:09:07 +0200 Subject: [PATCH 56/57] remove ios ephemeral --- .../Package.swift | 32 ------------------- .../FlutterGeneratedPluginSwiftPackage.swift | 3 -- .../Flutter/ephemeral/flutter_lldb_helper.py | 32 ------------------- .../ios/Flutter/ephemeral/flutter_lldbinit | 5 --- .../ephemeral/flutter_native_integration.env | 12 ------- 5 files changed, 84 deletions(-) delete mode 100644 permission_handler_apple/example/ios/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage/Package.swift delete mode 100644 permission_handler_apple/example/ios/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage/Sources/FlutterGeneratedPluginSwiftPackage/FlutterGeneratedPluginSwiftPackage.swift delete mode 100644 permission_handler_apple/example/ios/Flutter/ephemeral/flutter_lldb_helper.py delete mode 100644 permission_handler_apple/example/ios/Flutter/ephemeral/flutter_lldbinit delete mode 100644 permission_handler_apple/example/ios/Flutter/ephemeral/flutter_native_integration.env diff --git a/permission_handler_apple/example/ios/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage/Package.swift b/permission_handler_apple/example/ios/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage/Package.swift deleted file mode 100644 index 41fdeba8c..000000000 --- a/permission_handler_apple/example/ios/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage/Package.swift +++ /dev/null @@ -1,32 +0,0 @@ -// swift-tools-version: 5.9 -// The swift-tools-version declares the minimum version of Swift required to build this package. -// -// Generated file. Do not edit. -// - -import PackageDescription - -let package = Package( - name: "FlutterGeneratedPluginSwiftPackage", - platforms: [ - .iOS("13.0") - ], - products: [ - .library(name: "FlutterGeneratedPluginSwiftPackage", type: .static, targets: ["FlutterGeneratedPluginSwiftPackage"]) - ], - dependencies: [ - .package(name: "permission_handler_apple", path: "../.packages/permission_handler_apple"), - .package(name: "url_launcher_ios", path: "../.packages/url_launcher_ios-6.4.1"), - .package(name: "FlutterFramework", path: "../.packages/FlutterFramework") - ], - targets: [ - .target( - name: "FlutterGeneratedPluginSwiftPackage", - dependencies: [ - .product(name: "permission-handler-apple", package: "permission_handler_apple"), - .product(name: "url-launcher-ios", package: "url_launcher_ios"), - .product(name: "FlutterFramework", package: "FlutterFramework") - ] - ) - ] -) diff --git a/permission_handler_apple/example/ios/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage/Sources/FlutterGeneratedPluginSwiftPackage/FlutterGeneratedPluginSwiftPackage.swift b/permission_handler_apple/example/ios/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage/Sources/FlutterGeneratedPluginSwiftPackage/FlutterGeneratedPluginSwiftPackage.swift deleted file mode 100644 index a30d95a81..000000000 --- a/permission_handler_apple/example/ios/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage/Sources/FlutterGeneratedPluginSwiftPackage/FlutterGeneratedPluginSwiftPackage.swift +++ /dev/null @@ -1,3 +0,0 @@ -// -// Generated file. Do not edit. -// diff --git a/permission_handler_apple/example/ios/Flutter/ephemeral/flutter_lldb_helper.py b/permission_handler_apple/example/ios/Flutter/ephemeral/flutter_lldb_helper.py deleted file mode 100644 index a88caf99d..000000000 --- a/permission_handler_apple/example/ios/Flutter/ephemeral/flutter_lldb_helper.py +++ /dev/null @@ -1,32 +0,0 @@ -# -# Generated file, do not edit. -# - -import lldb - -def handle_new_rx_page(frame: lldb.SBFrame, bp_loc, extra_args, intern_dict): - """Intercept NOTIFY_DEBUGGER_ABOUT_RX_PAGES and touch the pages.""" - base = frame.register["x0"].GetValueAsAddress() - page_len = frame.register["x1"].GetValueAsUnsigned() - - # Note: NOTIFY_DEBUGGER_ABOUT_RX_PAGES will check contents of the - # first page to see if handled it correctly. This makes diagnosing - # misconfiguration (e.g. missing breakpoint) easier. - data = bytearray(page_len) - data[0:8] = b'IHELPED!' - - error = lldb.SBError() - frame.GetThread().GetProcess().WriteMemory(base, data, error) - if not error.Success(): - print(f'Failed to write into {base}[+{page_len}]', error) - return - -def __lldb_init_module(debugger: lldb.SBDebugger, _): - target = debugger.GetDummyTarget() - # Caveat: must use BreakpointCreateByRegEx here and not - # BreakpointCreateByName. For some reasons callback function does not - # get carried over from dummy target for the later. - bp = target.BreakpointCreateByRegex("^NOTIFY_DEBUGGER_ABOUT_RX_PAGES$") - bp.SetScriptCallbackFunction('{}.handle_new_rx_page'.format(__name__)) - bp.SetAutoContinue(True) - print("-- LLDB integration loaded --") diff --git a/permission_handler_apple/example/ios/Flutter/ephemeral/flutter_lldbinit b/permission_handler_apple/example/ios/Flutter/ephemeral/flutter_lldbinit deleted file mode 100644 index e3ba6fbed..000000000 --- a/permission_handler_apple/example/ios/Flutter/ephemeral/flutter_lldbinit +++ /dev/null @@ -1,5 +0,0 @@ -# -# Generated file, do not edit. -# - -command script import --relative-to-command-file flutter_lldb_helper.py diff --git a/permission_handler_apple/example/ios/Flutter/ephemeral/flutter_native_integration.env b/permission_handler_apple/example/ios/Flutter/ephemeral/flutter_native_integration.env deleted file mode 100644 index 17ec2cb49..000000000 --- a/permission_handler_apple/example/ios/Flutter/ephemeral/flutter_native_integration.env +++ /dev/null @@ -1,12 +0,0 @@ -FLUTTER_ROOT=/Users/au662726/fvm/versions/main -FLUTTER_APPLICATION_PATH=/Users/au662726/github_projects/flutter-permission-handler/permission_handler_apple/example -FLUTTER_FRAMEWORK_SWIFT_PACKAGE_PATH=/Users/au662726/github_projects/flutter-permission-handler/permission_handler_apple/example/ios/Flutter/ephemeral/Packages/.packages/FlutterFramework -COCOAPODS_PARALLEL_CODE_SIGN=true -FLUTTER_TARGET=lib/main.dart -FLUTTER_BUILD_DIR=build -FLUTTER_BUILD_NAME=1.0.0 -FLUTTER_BUILD_NUMBER=1 -DART_OBFUSCATION=false -TRACK_WIDGET_CREATION=true -TREE_SHAKE_ICONS=false -PACKAGE_CONFIG=.dart_tool/package_config.json From aa3061ab455a4fad0e62dab3902edb9504e95169 Mon Sep 17 00:00:00 2001 From: zeyus Date: Wed, 3 Jun 2026 15:11:31 +0200 Subject: [PATCH 57/57] remove main permission_handler example ios ephemeral --- permission_handler/example/ios/.gitignore | 10 ++++++ .../Package.swift | 32 ------------------- .../FlutterGeneratedPluginSwiftPackage.swift | 3 -- .../Flutter/ephemeral/flutter_lldb_helper.py | 32 ------------------- .../ios/Flutter/ephemeral/flutter_lldbinit | 5 --- .../ephemeral/flutter_native_integration.env | 12 ------- 6 files changed, 10 insertions(+), 84 deletions(-) delete mode 100644 permission_handler/example/ios/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage/Package.swift delete mode 100644 permission_handler/example/ios/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage/Sources/FlutterGeneratedPluginSwiftPackage/FlutterGeneratedPluginSwiftPackage.swift delete mode 100644 permission_handler/example/ios/Flutter/ephemeral/flutter_lldb_helper.py delete mode 100644 permission_handler/example/ios/Flutter/ephemeral/flutter_lldbinit delete mode 100644 permission_handler/example/ios/Flutter/ephemeral/flutter_native_integration.env diff --git a/permission_handler/example/ios/.gitignore b/permission_handler/example/ios/.gitignore index e96ef602b..8a62ea716 100644 --- a/permission_handler/example/ios/.gitignore +++ b/permission_handler/example/ios/.gitignore @@ -1,3 +1,9 @@ +.idea/ +.vagrant/ +.sconsign.dblite +.svn/ + +**/dgph *.mode1v3 *.mode2v3 *.moved-aside @@ -18,6 +24,7 @@ Flutter/App.framework Flutter/Flutter.framework Flutter/Flutter.podspec Flutter/Generated.xcconfig +Flutter/ephemeral/ Flutter/app.flx Flutter/app.zip Flutter/flutter_assets/ @@ -30,3 +37,6 @@ Runner/GeneratedPluginRegistrant.* !default.mode2v3 !default.pbxuser !default.perspectivev3 +# Swift Package Manager +.build/ +*.resolved diff --git a/permission_handler/example/ios/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage/Package.swift b/permission_handler/example/ios/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage/Package.swift deleted file mode 100644 index 41fdeba8c..000000000 --- a/permission_handler/example/ios/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage/Package.swift +++ /dev/null @@ -1,32 +0,0 @@ -// swift-tools-version: 5.9 -// The swift-tools-version declares the minimum version of Swift required to build this package. -// -// Generated file. Do not edit. -// - -import PackageDescription - -let package = Package( - name: "FlutterGeneratedPluginSwiftPackage", - platforms: [ - .iOS("13.0") - ], - products: [ - .library(name: "FlutterGeneratedPluginSwiftPackage", type: .static, targets: ["FlutterGeneratedPluginSwiftPackage"]) - ], - dependencies: [ - .package(name: "permission_handler_apple", path: "../.packages/permission_handler_apple"), - .package(name: "url_launcher_ios", path: "../.packages/url_launcher_ios-6.4.1"), - .package(name: "FlutterFramework", path: "../.packages/FlutterFramework") - ], - targets: [ - .target( - name: "FlutterGeneratedPluginSwiftPackage", - dependencies: [ - .product(name: "permission-handler-apple", package: "permission_handler_apple"), - .product(name: "url-launcher-ios", package: "url_launcher_ios"), - .product(name: "FlutterFramework", package: "FlutterFramework") - ] - ) - ] -) diff --git a/permission_handler/example/ios/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage/Sources/FlutterGeneratedPluginSwiftPackage/FlutterGeneratedPluginSwiftPackage.swift b/permission_handler/example/ios/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage/Sources/FlutterGeneratedPluginSwiftPackage/FlutterGeneratedPluginSwiftPackage.swift deleted file mode 100644 index a30d95a81..000000000 --- a/permission_handler/example/ios/Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage/Sources/FlutterGeneratedPluginSwiftPackage/FlutterGeneratedPluginSwiftPackage.swift +++ /dev/null @@ -1,3 +0,0 @@ -// -// Generated file. Do not edit. -// diff --git a/permission_handler/example/ios/Flutter/ephemeral/flutter_lldb_helper.py b/permission_handler/example/ios/Flutter/ephemeral/flutter_lldb_helper.py deleted file mode 100644 index a88caf99d..000000000 --- a/permission_handler/example/ios/Flutter/ephemeral/flutter_lldb_helper.py +++ /dev/null @@ -1,32 +0,0 @@ -# -# Generated file, do not edit. -# - -import lldb - -def handle_new_rx_page(frame: lldb.SBFrame, bp_loc, extra_args, intern_dict): - """Intercept NOTIFY_DEBUGGER_ABOUT_RX_PAGES and touch the pages.""" - base = frame.register["x0"].GetValueAsAddress() - page_len = frame.register["x1"].GetValueAsUnsigned() - - # Note: NOTIFY_DEBUGGER_ABOUT_RX_PAGES will check contents of the - # first page to see if handled it correctly. This makes diagnosing - # misconfiguration (e.g. missing breakpoint) easier. - data = bytearray(page_len) - data[0:8] = b'IHELPED!' - - error = lldb.SBError() - frame.GetThread().GetProcess().WriteMemory(base, data, error) - if not error.Success(): - print(f'Failed to write into {base}[+{page_len}]', error) - return - -def __lldb_init_module(debugger: lldb.SBDebugger, _): - target = debugger.GetDummyTarget() - # Caveat: must use BreakpointCreateByRegEx here and not - # BreakpointCreateByName. For some reasons callback function does not - # get carried over from dummy target for the later. - bp = target.BreakpointCreateByRegex("^NOTIFY_DEBUGGER_ABOUT_RX_PAGES$") - bp.SetScriptCallbackFunction('{}.handle_new_rx_page'.format(__name__)) - bp.SetAutoContinue(True) - print("-- LLDB integration loaded --") diff --git a/permission_handler/example/ios/Flutter/ephemeral/flutter_lldbinit b/permission_handler/example/ios/Flutter/ephemeral/flutter_lldbinit deleted file mode 100644 index e3ba6fbed..000000000 --- a/permission_handler/example/ios/Flutter/ephemeral/flutter_lldbinit +++ /dev/null @@ -1,5 +0,0 @@ -# -# Generated file, do not edit. -# - -command script import --relative-to-command-file flutter_lldb_helper.py diff --git a/permission_handler/example/ios/Flutter/ephemeral/flutter_native_integration.env b/permission_handler/example/ios/Flutter/ephemeral/flutter_native_integration.env deleted file mode 100644 index 89be47305..000000000 --- a/permission_handler/example/ios/Flutter/ephemeral/flutter_native_integration.env +++ /dev/null @@ -1,12 +0,0 @@ -FLUTTER_ROOT=/Users/au662726/fvm/versions/main -FLUTTER_APPLICATION_PATH=/Users/au662726/github_projects/flutter-permission-handler/permission_handler/example -FLUTTER_FRAMEWORK_SWIFT_PACKAGE_PATH=/Users/au662726/github_projects/flutter-permission-handler/permission_handler/example/ios/Flutter/ephemeral/Packages/.packages/FlutterFramework -COCOAPODS_PARALLEL_CODE_SIGN=true -FLUTTER_TARGET=lib/main.dart -FLUTTER_BUILD_DIR=build -FLUTTER_BUILD_NAME=1.0.0 -FLUTTER_BUILD_NUMBER=1 -DART_OBFUSCATION=false -TRACK_WIDGET_CREATION=true -TREE_SHAKE_ICONS=false -PACKAGE_CONFIG=.dart_tool/package_config.json