Flutter permission_handler Doesnt ask for notification - android

I'm using firabase notifications. But before initialize it i want to ask user to get permission. But when i using permission_handler its not asking to user even i uninstall and reinstall app. How can i solve it ? its my code for ask it :
#override
void initState() {
getPermissions();
}
void getPermissions() async {
var requestResult = await Permission.notification.request();
var isPermissionGranted = await Permission.notification.isGranted;
var isPermissionPermamentlyDenied =
await Permission.notification.isPermanentlyDenied;
//Its giving logs immediatly. Doesn't ask for permission.
log("requestResult $requestResult");
log("isPermissionGranted $isPermissionGranted");
log("isPermissionPermamentlyDenied $isPermissionPermamentlyDenied");

The following permissions will show no dialog:
Notification
Bluetooth
The following permissions will show no dialog, but will open the corresponding setting intent for the user to change the permission status:
manageExternalStorage
systemAlertWindow
requestInstallPackages
accessNotificationPolicy
link: https://pub.dev/packages/permission_handler

Is your test device iOS or android?
If it's iOS, you have to configure in Xcode. Under Signing & Capabilities.
Add Push Notifications.

Related

Check if "Remove permissions if app is unused" is disabled for a particular app

How can I programmatically determine whether the "Remove permissions if app is unused" setting is enabled or disabled for a particular app?
You can check whether the user has enabled or not, and you can also request them to disable it.
Check if the user has it enabled:
val future: ListenableFuture<Int> =
PackageManagerCompat.getUnusedAppRestrictionsStatus(context)
future.addListener(
{ onResult(future.get()) },
ContextCompat.getMainExecutor(context)
)
fun onResult(appRestrictionsStatus: Int) {
when (appRestrictionsStatus) {
// Status could not be fetched. Check logs for details.
ERROR -> { }
// Restrictions do not apply to your app on this device.
FEATURE_NOT_AVAILABLE -> { }
// Restrictions have been disabled by the user for your app.
DISABLED -> { }
// If the user doesn't start your app for months, its permissions
// will be revoked and/or it will be hibernated.
// See the API_* constants for details.
API_30_BACKPORT, API_30, API_31 ->
handleRestrictions(appRestrictionsStatus)
}
}
ask to disable it:
fun handleRestrictions(appRestrictionsStatus: Int) {
// If your app works primarily in the background, you can ask the user
// to disable these restrictions. Check if you have already asked the
// user to disable these restrictions. If not, you can show a message to
// the user explaining why permission auto-reset and Hibernation should be
// disabled. Tell them that they will now be redirected to a page where
// they can disable these features.
Intent intent = IntentCompat.createManageUnusedAppRestrictionsIntent
(context, packageName)
// Must use startActivityForResult(), not startActivity(), even if
// you don't use the result code returned in onActivityResult().
startActivityForResult(intent, REQUEST_CODE)
}
Source: https://android-developers.googleblog.com/2021/09/making-permissions-auto-reset-available.html
That's a great question and I'm still trying to determine what that even means.
It appears on my Bixby app that came installed on my Samsung. It goes off at random at least 4 times an hour.
I've disabled it many times and I feel "remove permissions if app is unused" is worded in such a confusing way intentionally with the intention to be invasive.

flutter location , Unhandled Exception: PlatformException(PERMISSION_DENIED_NEVER_ASK, Background location permission denied forever

I'm using Location flutter package to access the user's background location, first time any user opens the app it asks for permission, and when the user accepts it brings back this error in the console
Unhandled Exception: PlatformException(PERMISSION_DENIED_NEVER_ASK, Background location permission denied forever - please open app settings, null, null)
if the user closed the app and reopened it .. it works perfectly fine ( fetches location in both foreground and background) without even asking again for location permission.
Following the getting started guide in the package itself, here is how I added permission to my AndroidManifest.xml file :
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
I've been working on this issue and I discovered that the problem is when you use location.enableBackgroundMode() then choose always when you hit back first time it throws an exception and isBackgroundModeEnabled will be false too "despite the backgroundmode is enabled in system" and you have to restart the app to check if background mode is enabled correctly.
but, I've found that calling location.enableBackgroundMode() again is solving the issue too and it really doesn't ask for enabling background again but it somehow make isBackgroundModeEnabled return true value. Here's my fix code:
Future<bool> enableBackgroundMode() async {
bool _bgModeEnabled = await location.isBackgroundModeEnabled();
if (_bgModeEnabled) {
return true;
} else {
try {
await location.enableBackgroundMode();
} catch (e) {
debugPrint(e.toString());
}
try {
_bgModeEnabled = await location.enableBackgroundMode();
} catch (e) {
debugPrint(e.toString());
}
print(_bgModeEnabled); //True!
return _bgModeEnabled;
}
}

Permission request flutter app after denial

I'm developing a flutter application, I need to manage the permission request, but I don't know how to treat a particular occurrence:
If I deny two times the same permission through the popup it could be impossible approve it later 'cause the popup will not appair again.
Future<void> requestStoragePermission() async{
var status = await Permission.storage.status;
if(status.isPermanentlyDenied){
await AppSettings.openAppSettings();
} else {
await Permission.storage.request();
}
}
I don't understand how to distinguish when the permission has not yet been granted or when it has been refused several times because the function: Permission.storage.status always returns "denied".
****** EDIT ******
The problem arises when the user refuses the same permission several times (2 times) because the permissions request popup is no longer shown, in which case it is necessary to manually open the application settings and modify the permissions by hand. I have to make sure that: the first two times I request permissions with the popup then I should open the settings screen
I have always managed my permissions using two statuses granted and limited (used only for iOS14+). These two permissions are the only truethy statuses. All the others are falsey statuses.
the permission_handler package handles a lot of logic for you already. Before it makes the request, it will check the status to see if it is already defined. If it is, then it will return the status. If the permission has never been requested, then it will request the permission.
Personally, I set up a generic method for a permission request, to keep things DRY.
Future<bool> requestPermission(Permission setting) async {
// setting.request() will return the status ALWAYS
// if setting is already requested, it will return the status
final _result = await setting.request();
switch (_result) {
case PermissionStatus.granted:
case PermissionStatus.limited:
return true;
case PermissionStatus.denied:
case PermissionStatus.restricted:
case PermissionStatus.permanentlyDenied:
return false;
}
}
I then make a request like
final canUseStorage = await requestPermission(Permission.storage);
if (canUseStorage) {
// do something with storage
}
If you have UI that is dependent on a status from Permission, then you still call Permission.storage.status.
[EDIT]
At the moment, you can't track how many times the request pop-up has been shown via permission_handler. It only returns the status. You would need to take the user to the settings depending on the returned status value.
Side Note
Instead of taking the user directly to the settings. Maybe you show a pop up saying "Looks like we don't have permission...", with a button that the user can tap to go to the settings, provides the user with some context as to why they need to go to their settings. And it's also a better user experience!

How to track location in background with Flutter?

I have been working on a team developing an app in Flutter. We need to track the distance travelled using the GPS but the challenge is that Flutter no longer allows both foreground and background location tracking (even with a coarse level of accuracy).
Based on a review of the latest Google guidelines, it seems like Google should allow our app to track the device when it’s in the background, but it does not. In fact, turning on foreground and background location services seemed to be working a month or two back. We have tried both the location and geolocation packages, to no avail. Either of them immediately stops tracking when the app is in the background and we get one big jump in location when the app is returned to the foreground.
Here’s what we’ve tried
AndroidManifest.xml
...
<uses-permission android:name="android.permission.ACCESS_COURSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
...
App Code Using Geolocation
...
serviceEnabled = await Geolocator.isLocationServiceEnabled();
if (!serviceEnabled) {
return Future.error('Location services are disabled.');
}
permission = await Geolocator.checkPermission();
if (permission == LocationPermission.denied) {
permission = await Geolocator.requestPermission();
if (permission == LocationPermission.denied) {
return Future.error('Location permissions are denied');
}
}
//Permission returns denied Location
//this is due to the background permission in the android manifest
//turn off background permission and the permission is allowed
if (permission == LocationPermission.deniedForever)
return Future.error(
'Location permissions are permanently denied, we cannot request permissions.');
}
...
App Code Using Location
_serviceEnabled = await location.serviceEnabled();
if (!_serviceEnabled) {
_serviceEnabled = await location.requestService();
if (!_serviceEnabled) {
print('Service could not be enabled');
return false;
}
// This code throws and exception even if I respond to the
// Google prompts and I select allow location service and all the time access
try {
await location.enableBackgroundMode(enable: true);
} catch(error) {
print("Can't set background mode");
}
Any guidance for how to achieve this would be much appreciated.
Natively, Flutter still doesn't support background localization.
I've seen some android-specific forms, but nothing was effective.
But actively looking, I found this lib:
https://pub.dev/packages/flutter_background_geolocation
It's a paid lib, to be used in production (for android keys. iOS is free). And it works perfectly.
Despite having a cost (which is unique and for life) the cost benefit is very good.
Highly recommend.
Note: Their documentation and support is wonderful.
Currently, I am using the background_fetch because everyone can't afford flutter_background_geolocation pricing BTW this plugin is also from the same company
background_fetch: ^0.7.2
So far it's working fine in Android will work nicely but in ios, it will take some time reason being Apple's background process algorithm once it will get used then It will be fine in apple as well.
Here is the link-:
https://pub.dev/packages/background_fetch
Setup
int status = await BackgroundFetch.configure(
BackgroundFetchConfig(
minimumFetchInterval: 30,
stopOnTerminate: true,
enableHeadless: false,
startOnBoot: false,
requiresBatteryNotLow: false,
requiresCharging: false,
requiresStorageNotLow: false,
requiresDeviceIdle: false,
requiredNetworkType: NetworkType.NONE),
(taskId){
// This is the fetch-event callback.
},
(taskId){
// This task has exceeded its allowed running time.
// You must stop what you're doing and immediately finish(taskId)
});
print('[BackgroundFetch] configure success: $status');
The location plugin works perfectly and is free to use.
There could be several reasons that it did not work for you like some other external application killing your app in background or just your devices default OS could be stopping the application after a while in background.
Call the service enabling code in the initState of your Stateful Widget.
You can listen to the background changes as:
location.onLocationChanged.listen((LocationData currentLocation) {
// do whatever you want with new location
});
You need this flutter_background_service package for this.
This package will help you to run the location service in a separate isolate.
Try using flutter_background_service
flutter_background_service: ^2.4.6
Required setup:
await service.configure(
androidConfiguration: AndroidConfiguration(
onStart: onStart,
isForegroundMode: true,
notificationChannelId: 'my_foreground',
initialNotificationTitle: 'AWESOME SERVICE',
initialNotificationContent: 'Initializing',
foregroundServiceNotificationId: 888,
),);
Use geoloactor within this background service,
#pragma('vm:entry-point')
void onStart(ServiceInstance service) async {
// use geolocator to get location here
}
This will shoot a notification and runs your code inside onStart on a separate isolate. The code inside isolate runs (even when the app is cleared from the recent) till you stop the background service.

Open specific app's permission setting flutter?

I wonder how to open permission setting for specific app in Flutter? I search on internet but no article show me how to do that, just some solutions for android, like this. Open app permission settings
hi there try this code to ask for permission and open app settings like for location with the help of permission_handler(https://pub.dev/packages/permission_handler) package
Future<void> _request_permission(context,Function fn)async{
final Permission location_permission=Permission.location;
bool location_status=false;
bool ispermanetelydenied= await location_permission.isPermanentlyDenied;
if(ispermanetelydenied) {
print("denied");
await openAppSettings();
}else{
var location_statu = await location_permission.request();
location_status=location_statu.isGranted;
print(location_status);
}
}
Here this function allows you to open the app setting and manage permission in the case user permanently denied the permission
openAppSettings();
thanks
#azad-prajapat
And when I look at the package code I found this
/// Opens the app settings page.
///
/// Returns [true] if the app settings page could be opened, otherwise
/// [false].
Future<bool> openAppSettings() {
throw UnimplementedError('openAppSettings() has not been implemented.');
}

Categories

Resources