Flutter: Location permission: when in use or always - flutter

I'm trying to know if the user has selected "only when in use" or "always" for the location.
https://pub.dev/packages/location_permissions
I tried this code from the package:
ServiceStatus serviceStatus =
await LocationPermissions().checkServiceStatus();
print(serviceStatus);
But it prints:
ServiceStatus.enabled
Is there a possibility (perhaps with another package) to know this?
Thanks in advance!

permission_handler can do this.
enum PermissionGroup {
...
/// Android: Fine and Coarse Location
/// iOS: CoreLocation - Always
locationAlways,
/// Android: Fine and Coarse Location
/// iOS: CoreLocation - WhenInUse
locationWhenInUse
}
Requesting permissions:
final ph = PermissionHandler();
final requested = await ph.requestPermissions([
PermissionGroup.locationAlways,
PermissionGroup.locationWhenInUse
]);
final alwaysGranted = requested[PermissionGroup.locationAlways] == PermissionStatus.granted;
final whenInUseGranted = requested[PermissionGroup.locationWhenInUse] == PermissionStatus.granted;
Add these permissions to AndroidManifest.xml inside <manifest> tag:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.test_project">
<!-- add these -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
...
And these to <dict> tag of Info.plist:
<!-- Permission options for the `location` group -->
<key>NSLocationWhenInUseUsageDescription</key>
<string>Need location when in use</string>
<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>Always and when in use!</string>
<key>NSLocationUsageDescription</key>
<string>Older devices need location.</string>
<key>NSLocationAlwaysUsageDescription</key>
<string>Can I haz location always?</string>

This library is support Stream so you can check like that.
LocationPermissions().serviceStatus.listen((event) {
if(event == ServiceStatus.disabled){
print('Location Disabled');
}else{
print('Location Enabled');
});
Good luck.

Geolocator package may be used for that. From its readMe page:
This method returns a value of the GeolocationStatus enum indicating
the availability of the location services on the device. Optionally
you can specify if you want to test for
GeolocationPermission.locationAlways or
GeolocationPermission.locationWhenInUse
. Have a look here - https://pub.dev/packages/geolocator

Related

Using permission Handler - Nearby device Permission Not working

I am building a Flutter Application that needs to connect to bluetooth devices nearby.
I followed the documentation for permission_handler here
and it works (kinda) but strangely enough it does not fully set the nearby device permission properly because when I go scan for nearby devices it is unable to find any.
I know this is the problem because when I manually toggle the permission in the app settings it works as intended.
For reference my androidmanifest.xml:
<!-- Permissions options for the `contacts` group -->
<uses-permission android:name="android.permission.READ_CONTACTS"/>
<uses-permission android:name="android.permission.WRITE_CONTACTS"/>
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
<!-- Permissions options for the `storage` group -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
Code to check if permission is granted:
bool permGranted = true;
var status = await Permission.location.status;
if (status.isDenied) {
permGranted = false;
if (await Permission.location.request().isGranted) {
permGranted = true;
}
}
if (permGranted) {
_logMessage('Start ble discovery');
...
thanks in advance for any help!
Integrating the example app into my existing app is what helped me solve my error in the end.
The problem was that I was not allowing all the permissions I needed before attempting to scan for devices nearby.
it turns out when you manuelly toggle location on and off you also accept many other permissions as well.
here is the code needed:
bool permGranted = true;
var status = await Permission.location.status;
if (status.isDenied) {
permGranted = false;
Map<Permission, PermissionStatus> statuses = await [
Permission.location,
Permission.bluetoothScan,
Permission.bluetoothAdvertise,
Permission.bluetoothConnect
].request();
if (statuses[Permission.location]!.isGranted &&
statuses[Permission.bluetoothScan]!.isGranted &&
statuses[Permission.bluetoothAdvertise]!.isGranted &&
statuses[Permission.bluetoothConnect]!.isGranted) {
permGranted = true;
} //check each permission status after.
}

Flutter health package - access denied! - Google fit

I am developing an app in Flutter with Health package, but my app isn´t working.
I download the google-services.json, already edited the manifest file with the package name and use the following permissions :
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACTIVITY_RECOGNITION"/>
<uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /
I use the example I found in the page of this package:
// create a HealthFactory for use in the app
HealthFactory health = HealthFactory();
// define the types to get
var types = [
HealthDataType.STEPS,
HealthDataType.WEIGHT,
HealthDataType.HEIGHT,
HealthDataType.BLOOD_GLUCOSE,
];
// requesting access to the data types before reading them
bool requested = await health.requestAuthorization(types);
var now = DateTime.now();
// fetch health data from the last 24 hours
List<HealthDataPoint> healthData = await health.getHealthDataFromTypes(
now.subtract(Duration(days: 1)), now, types);
// request permissions to write steps and blood glucose
types = [HealthDataType.STEPS, HealthDataType.BLOOD_GLUCOSE];
var permissions = [
HealthDataAccess.READ_WRITE,
HealthDataAccess.READ_WRITE
];
await health.requestAuthorization(types, permissions: permissions);
// write steps and blood glucose
bool success = await health.writeHealthData(10, HealthDataType.STEPS, now, now);
success = await health.writeHealthData(3.1, HealthDataType.BLOOD_GLUCOSE, now, now);
// get the number of steps for today
var midnight = DateTime(now.year, now.month, now.day);
int? steps = await health.getTotalStepsInInterval(midnight, now);
And the console log look like this:
D/FLUTTER_HEALTH(17489): Access Denied!
W/FLUTTER_HEALTH::ERROR(17489): There was an error adding the DataSet
W/FLUTTER_HEALTH::ERROR(17489): com.google.android.gms.common.api.ApiException: 4: The user must be signed in to make this API call.
W/FLUTTER_HEALTH::ERROR(17489): at com.google.android.gms.common.internal.ApiExceptionUtil.fromStatus(com.google.android.gms:play-services-base##18.0.1:3).
Please help me... I´ve tried for a long time :(
The error says you must signed in to make API call. You must generate OAuth client IDs, handle scopes, etc in order to use the API. This is done through GCP. Also, make sure that the email is added as test user for your project.

Permission Denied even after granting the Storage Permission

I have added every thing required to download files to local storage still I'm getting this error
[ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception:
FileSystemException: Creation failed, path =
'/storage/emulated/0/uth_content' (OS Error: Operation not permitted,
errno = 1)
In Manifest
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_MEDIA_LOCATION"/>
android:requestLegacyExternalStorage="true"
android:hardwareAccelerated="true"
<application
android:requestLegacyExternalStorage="true" >
In pubspec.yaml
permission_handler: ^6.1.1
My Dart File
#override
Future<int> downloadZipFile() async{
Directory extStorage = await _externalDataSource.GetExtStoragePath();
if(extStorage !=null) {
var response = await _apiDataSource.downloadZipContent(extStorage.path);
File zipfile = await response.zipFile;
debugPrint("Downloaded file :" + zipfile.path + "Exist: " + zipfile.existsSync().toString());
return response.statusCode;
}
else{
debugPrint("Path is empty");
createFolder("uth_content");
}
}
Future<String> createFolder(String cow) async {
final folderName = cow;
final path = Directory("/storage/emulated/0/$folderName");
var status = await Permission.storage.status;
if (!status.isGranted) {
await Permission.storage.request();
}
if ((await path.exists())) {
return path.path;
} else {
path.create();
return path.path;
}
}
How can I ensure that the folder is created, my android api is 30
You are missing this permission in your AndroidManifest.xml
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
To get the permission use
if (await Permission.manageExternalStorage.request().isGranted) {...}
NOTE: This permission is considered pretty risky so play store will reject your app unless it's your app's core functionality.
This is what google says
Core functionality is defined as the main purpose of the app. Without
this core functionality, the app is "broken" or rendered unusable. The
core functionality, as well as any core features that comprise this
core functionality, must all be prominently documented and promoted in
the app's description.
And if you are planning to create a file in an external directory and you are not able to find it, it's because you'd have to tell the device to refresh for the files. So I'd recommend using this package and passing your newly created file path to it or if you wanna do it manually with kotlin here's the code
private fun broadcastFileUpdate(path: String) {
context.sendBroadcast(Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(File(path))))
println("updated!")
}

I get a `cannot open camera "0" without camera permission` Error when I try to open a camera to scan a QR code

I get a cannot open camera "0" without camera permission Error when I try to open a camera to scan a QR code.
I have a QR code scanner function that does not open the camera. The scanner screen appears but I do not see the box with the line inside for scanning.
I have also added camera permissions in the Android manifest
Android Manifest Permissions
<uses-permission android:name="android.permission.CAMERA"/>
<uses-feature android:name="android.hardware.camera"
android:required="false"/>
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
The Scanner Function is below
Future <void> scanqr() async {
final qrCode = await scanner.scan();
setState(() {
this.qrCode = qrCode;
});
}
//use permission_handler package and use the below code.. it will work fine
Future <void> scanqr() async {
await Permission.camera.request();
final qrCode = await scanner.scan();
setState(() {
this.qrCode = qrCode;
});
}

How to get push notification click event with Flutter Huawei Push Kit plugin?

I am integrating Huawei Push Kit (https://pub.dev/packages/huawei_push) in Flutter application and everything works fine except I am unable to get the event when received push notification message is clicked to be able to act on it.
Is this possible to achieve via this plugin or do I need to write this part in native Android code?
Currently, you can achieve this with another plugin that listens for the custom intents. Uni_links package from pub.dev is easy to use. Here is a quick guide to uni_links package:
Add uni_links to your pubspec.yaml file:
dependencies:
flutter:
sdk: flutter
huawei_push: 4.0.4+300
uni_links: 0.4.0
Define an intent filter on your AndroidManifest.xml file:
<application
<!-- . . . Other Configurations . . . -->
<activity/>
<!-- . . . Other Configurations . . . -->
<!-- Add the intent filter below.(inside the application and activity tags) -->
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="app"/>
</intent-filter>
</activity>
</application
Call the uni links methods in your initState() that will listen for the custom intents. The notification's custom intent I've sent from the Push Kit Console looks like this:
app:///ContentPage?name=Push Kit&url=https://developer.huawei.com/consumer/en/hms/huawei-pushkit
// Get the initial intent that opens the app
Future<void> initInitialLinks() async {
// Platform messages may fail, so we use a try/catch PlatformException.
try {
String initialLink = await getInitialLink();
if (initialLink != null) {
var uri = Uri.dataFromString(initialLink);
String page = uri.path.split('://')[1];
String serviceName = uri.queryParameters['name'];
String serviceUrl = uri.queryParameters['url'];
try {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
Navigator.of(context).pushNamed(
page,
arguments: ContentPageArguments(serviceName, serviceUrl),
); // Navigate to the page from the intent
});
} catch (e) {
Push.showToast(e);
}
}
} on PlatformException {
print('Error: Platform Exception');
}
}
// Get intents as a stream
Future<Null> initLinkStream() async {
if (!mounted) return;
_sub = getLinksStream().listen((String link) {
var uri = Uri.dataFromString(link);
String page = uri.path.split('://')[1];
// Parse the string ...
Navigator.of(context).pushNamed(page); // Navigate to a page from the intent
}, onError: (err) {
print("Error while listening for the link stream: " + err.toString());
});
}
For more information, visit: Deep Linking on Flutter using Huawei Push Kit’s Custom Intents
The accompanying github repository of the article includes the codes.
I also looked into their flutter plugin and couldn't any method for that. I guess you will have to write platform specific code and for that you can refer to their demo native android project with PushKit.
https://github.com/HMS-Core/hms-push-clientdemo-android