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.
Related
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.
}
I have a base64 encoded string of a PDF file. I'm trying to save it as a file in the android device. My code runs with no error, but i can't find the file.
Uint8List bytes = base64.decode(encodedStr);
String dir = (await getExternalStorageDirectories(
type: StorageDirectory.downloads))!
.first
.path;
File file = File("$dir/" +
DateTime.now().millisecondsSinceEpoch.toString() +
".pdf");
await file.writeAsBytes(bytes);
Also, I tried to include code to ask for permission before trying to save the file, but it didn't change anything.
var status = await Permission.storage.status;
if (!status.isGranted) {
await Permission.storage.request();
}
if (await Permission.storage.request().isGranted) {
try {
await file.writeAsBytes(bytes);
} catch (e) {
print(e);
}
}
And, as another attempt, I included these permission on my AndroidManifest file. Also, no changes.
<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"/>
<uses-permission android:name="android.permission.READ_INTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
//dir = /storage/emulated/0/Android/data/com.xxxxxxxxxxxxxxxx.xxxxx/files/Download
//dir + file = /storage/emulated/0/Android/data/com.xxxxxxxxxxxxxxxx.xxxxx/files/Download/1655924904315.pdf
//file path after written = /storage/emulated/0/Android/data/com.xxxxxxxxxxxxxxxx.xxxxx/files/Download/1655924904315.pdf
Is there anything wrong with my code or something that I can change in order for it to work ?
The above code is using path_provider and permission_handler packages and was tested in an emulator and in a physical device.
Thanks.
Try importing io and use file of io and use this package https://pub.dev/packages/pdf
import 'dart:io' as io;
import 'package:pdf/pdf.dart';
import 'package:pdf/widgets.dart' as pw;
final pdf = pw.Document();
final dir = await getTemporaryDirectory();
final path = "${dir.path}/pdfname.pdf";
final file = await io.File(path).writeAsBytes(pdf.save());
It happens that the files are being correctly generated, but they are being saved in the application's directory. A download folder has being created and the files are being saved there. I didn't find the files searching via android, but when I connected my physical device to a PC I was able the find them.
It seems that this has something to do with this https://github.com/flutter/flutter/issues/35783 . Path_provider started to return application document directory after 1.1.0 instead of the general downloads folder.
I'll check how to access the path I want correctly.
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 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;
});
}
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