requestPermission method
Future<NotificationResult<NotificationPermissionStatus> >
requestPermission({
- BuildContext? context,
- bool includeExactAlarm = false,
Requests notification permission and returns the resulting state.
When context is supplied, it can be used to show the configured
explanation if permission must be changed in system settings. Set
includeExactAlarm to also check and request Android exact-alarm access.
Implementation
Future<NotificationResult<NotificationPermissionStatus>> requestPermission({
BuildContext? context,
bool includeExactAlarm = false,
}) async {
final requestContext = context;
final failure = _precondition<NotificationPermissionStatus>();
if (failure != null) return failure;
if (!_hasAnyLocalFeature) {
return const NotificationFailureResult(
ProviderNotEnabledFailure('permission (no local features enabled)'),
);
}
var statusResult = await checkPermission();
if (requestContext != null && !requestContext.mounted) {
return _cancelledPermissionRequest();
}
if (statusResult.isFailure) return statusResult;
var status = statusResult.valueOrNull!;
if (!status.isGranted && status.canRequest) {
final shouldRequest = await _shouldRequestNatively(status);
if (requestContext != null && !requestContext.mounted) {
return _cancelledPermissionRequest();
}
if (shouldRequest.isFailure) {
return NotificationFailureResult(shouldRequest.failureOrNull!);
}
if (shouldRequest.valueOrNull!) {
statusResult = await _factory!.permissionRepo.request();
if (requestContext != null && !requestContext.mounted) {
return _cancelledPermissionRequest();
}
if (statusResult.isFailure) return statusResult;
status = statusResult.valueOrNull!;
_publishPermissionStatus(status);
}
}
if (!status.isGranted && !status.canRequest && requestContext != null) {
final shouldShow = await _factory!.storage.shouldShowPermissionDialog(
cooldown: _config!.permissionConfig.dialogCooldown,
);
if (!requestContext.mounted) return _cancelledPermissionRequest();
if (shouldShow.isFailure) {
return NotificationFailureResult(shouldShow.failureOrNull!);
}
if (shouldShow.valueOrNull!) {
final dialog =
_config!.permissionDialog ?? const DefaultPermissionDialog();
final openSettings = await dialog.show(
context: requestContext,
title: _config!.permissionConfig.dialogTitle,
message: _config!.permissionConfig.dialogMessage,
openSettingsLabel: _config!.permissionConfig.openSettingsLabel,
notNowLabel: _config!.permissionConfig.notNowLabel,
);
if (!requestContext.mounted) return _cancelledPermissionRequest();
final dismissed = await _factory!.storage.recordPermissionPromptShown();
if (!requestContext.mounted) return _cancelledPermissionRequest();
if (dismissed.isFailure) {
return NotificationFailureResult(dismissed.failureOrNull!);
}
if (openSettings) {
final opened = await openNotificationSettings();
if (!requestContext.mounted) {
return _cancelledPermissionRequest();
}
if (opened.isFailure) {
return NotificationFailureResult(opened.failureOrNull!);
}
await _waitForResume(_config!.permissionConfig.settingsReturnTimeout);
if (!requestContext.mounted) {
return _cancelledPermissionRequest();
}
statusResult = await checkPermission();
if (!requestContext.mounted) {
return _cancelledPermissionRequest();
}
if (statusResult.isFailure) return statusResult;
status = statusResult.valueOrNull!;
}
}
}
if (!status.isGranted) return NotificationSuccess(status);
if (includeExactAlarm) {
final exact = await _factory!.permissionRepo.canScheduleExactAlarms();
if (requestContext != null && !requestContext.mounted) {
return _cancelledPermissionRequest();
}
if (exact.isFailure) {
return NotificationFailureResult(exact.failureOrNull!);
}
if (!exact.valueOrNull!) {
final request = await _factory!.permissionRepo
.requestExactAlarmPermission();
if (requestContext != null && !requestContext.mounted) {
return _cancelledPermissionRequest();
}
if (request.isFailure || request.valueOrNull != true) {
return const NotificationFailureResult(ExactAlarmPermissionFailure());
}
final confirmed = await _factory!.permissionRepo
.canScheduleExactAlarms();
if (requestContext != null && !requestContext.mounted) {
return _cancelledPermissionRequest();
}
if (confirmed.isFailure || confirmed.valueOrNull != true) {
return const NotificationFailureResult(ExactAlarmPermissionFailure());
}
}
}
return NotificationSuccess(status);
}