I'm using qr_code_scanner to scan barcodes in my Flutter app and it works fine for Android, but when I try to scan for iOS a pop-up appears and looks like:
I'm using the descriptions Flutter code that looks like the following:
QRView(
key: qrKey,
onQRViewCreated: (controller) => {
controller.scannedDataStream.listen((code) async {
...
})
})
And in my Info.plist file I have the following fields:
<key>io.flutter.embedded_views_preview</key>
<true/>
<key>NSCameraUsageDescription</key>
<string>Camera permission is required to scan QR codes.</string>
However even with these settings set, I can't seem to figure out how to have access to the camera. Thanks for any help.
Update
I followed #EvgeniyTrubilo suggestion and used permission_handler to request permission using the following code:
void getCameraPermission() async {
print(await Permission.camera.status); // prints PermissionStatus.granted
var status = await Permission.camera.status;
if (!status.isGranted) {
final result = await Permission.camera.request();
if (result.isGranted) {
setState(() {
canShowQRScanner = true;
});
} else {
Scaffold.of(context).showSnackBar(
SnackBar(content: Text('Please enable camera to scan barcodes')));
Navigator.of(context).pop();
}
} else {
setState(() {
canShowQRScanner = true;
});
}
}
The first time this code was executed it successfully requested permission to access camera, and once permission was granted, the same error showed up. Sequential tries the print statement at the top of the above function said the Permission was granted??
Update 2x
Just realized you can mock the camera in an iOS simulator like you can on Android. I will try this on an actual device and update.
You can use permission_handler. With this, you could ask for camera permission before build QRView. Of course, you should build QRView after camera permission is enabled.
I'm not sure it would be right solution for your issue, but I think that would be an awesome improvement.
Related
I am developing in Flutter and am trying to get GPS information using the geolocator package.
I was able to get GPS information on the emulator with no problem, but when I started the app on the actual device, I could not get GPS.
The app was working fine, so it was not an error, but there was a message.
"This method can cause UI unresponsiveness if invoked on the main thread. Instead, consider waiting for the -locationMana gerDidChangeAuthorization: callback and checking authorizationStatus first."
Code on Flutter side
Future<Position> getGps(BuildContext context) async {
return await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.high,
timeLimit: Duration(seconds: 5),
);
}
(WARNING)Code on IOS side
- (ServiceStatus)checkServiceStatus:(PermissionGroup)permission {
return [CLLocationManager locationServicesEnabled] ? ServiceSttus Enabled
: ServiceStatusDisabled;
}
2023/1/26 added
I had added it to info.plist. Still, I am not getting GPS information.
info.plist
<key>NSLocationAlwaysUsageDescription</key>
<string>Access location information to get a location</string>.
<key>NSLocationWhenInUseUsageDescription</key>
<string>Access location information to get location</string>
How do I get GPS information?
Permission to acquire location services is granted.
iOS:16.2
xcode: 14
geolocator: 7.7.1
2023/1/26 added
Current Status
Emulator(Android) ...〇(GPS information has been acquired.)
Emulator(iOS(iphone SE2)) ...〇(GPS information has been acquired.)
Actual Device(iOS(iphone SE2)) ...× (GPS cannot be acquired)
Try this
Add "location_permissions: 3.0.0+1" this dependencies in "pubspec.yaml". Please note that I did that for flutter 1.22.0 so for flutter 2.0 this might be an issue.
Import the package in the file
import 'package:location_permissions/location_permissions.dart';
Add the following code on the page where you want to ask for permission. (Better to add that on the very first page of your app.)
#override
void initState() {
....
if (Platform.isIOS) {
location_permission();
}
....
}
Add the following two methods in the same file
void location_permission() async {
final PermissionStatus permission = await _getLocationPermission();
if (permission == PermissionStatus.granted) {
final position = await geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.best);
// Use the position to do whatever...
}
}
Future<PermissionStatus> _getLocationPermission() async {
final PermissionStatus permission = await LocationPermissions()
.checkPermissionStatus(level: LocationPermissionLevel.location);
if (permission != PermissionStatus.granted) {
final PermissionStatus permissionStatus = await LocationPermissions()
.requestPermissions(
permissionLevel: LocationPermissionLevel.location);
return permissionStatus;
} else {
return permission;
}
}
I was able to solve my problem.
I thought it was a permissions issue in my case, but it was just a location acquisition timeout. I modified the location acquisition timeout from 5 seconds to 20 seconds and was able to get the necessary information without any problems.
The warnings are still there, but we decided not to worry about them since we were able to solve the problem.
return await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.high,
timeLimit: Duration(seconds: 20),
);
I am using the native camera (iOS/Android) calling as following:
async function takePhoto() {
const photo = await ImagePicker.launchCameraAsync(cameraOptions);
if (photo.cancelled) {
return '';
}
return photo.uri;
}
Since upgraded from Expo 39 to 42 it is broken (see screenshots)
Portrait
Landscape
It seems to me, that it is beeing opened as Modal. I don't know where to change this.
Expected behaviour:
Display of camera in fullscreen as native camera under iOS
Update: 20210730: Meanwhile it has been opend as a bug/issue:
https://github.com/expo/expo/issues/13614
Any ideas, suggestions - especially in terms of a workaround?
Thanks a lot.
I've done a massive upgrade from EXPO SDK 37 to EXPO SDK 42. Had to change alot of things around camera, location and permissions.
I do not experience this behavior when using the following (I cannot see your import statements or your package versions but this is what I've implemented and experience no issue)
// Import statements...
import * as ImagePicker from 'expo-image-picker';
import * as FileSystem from 'expo-file-system';
import { Camera } from 'expo-camera';
// Code within Component
const takePicture = async () => {
// You MUST ask for permissions first.
const permissions = {
[Camera]: await Camera.requestPermissionsAsync()
};
// If denied let the user know its required.
if (permissions[Camera].status !== 'granted') {
return Promise.reject(new Error('Camera Permission Required'));
}
// Then let them launch the camera and perform any other task
await ImagePicker.launchCameraAsync({
allowsEditing: false
})
.then(({ uri }) => imageProcesser(uri))
.then(res => onImageAdded(res))
.catch((e) => console.log(e));
};
// These are my concerning package versions
"expo-camera": "^11.2.2"
"expo-file-system": "~11.1.3",
"expo-image-picker": "~10.2.2",
"expo": "^42.0.3"
I am building an app using React Native and photo upload is one of its key functions. Here is what I am trying to do:
When the user clicks on the button to open the camera roll, tell whether the user allowed camera access or not.
If the user didn't allow, show an alert to ask the user to turn on the permission from settings to ensure proper experience on the app.
Where should I look at to start tackling this? I am new to programming in general and not familiar at all with native code. I know this is a high-level question so some high-level guidance will be appreciated. Thanks!
You can start at looking at react-native-permissions module. It allows you to ask for any kind of permissions that a mobile app can require, and also the dialogs are handled natively so you dont have to worry about building the alerts yourself.
https://github.com/zoontek/react-native-permissions
Here's an example on how to handle image selection with permissions
import ImagePicker, {
ImagePickerOptions,
ImagePickerResponse,
} from 'react-native-image-picker';
import { openSettings } from 'react-native-permissions';
import { alertWrapper } from './alert';
export const selectPicture = (options: ImagePickerOptions) => {
const pickerPromise = new Promise<ImagePickerResponse>((resolve) => {
try {
ImagePicker.showImagePicker(options, (response: ImagePickerResponse) => {
if (response.didCancel) {
return;
}
if (response.error) {
if (response.error.includes('permissions')) {
alertWrapper('Error', response.error, [
{ text: 'Open Settings', onPress: () => openSettings() },
]);
}
return;
}
resolve(response);
});
} catch (e) {
throw e;
}
});
return pickerPromise;
};
I am developing a mobile app in flutter that requires the user to select an image from the gallery.
I am using image_picker: ^0.6.7+11 and here is my code:
if (await Permission.photos.request().isGranted) {
try {
final image =
await ImagePicker().getImage(source: ImageSource.gallery);
if (image != null) {
photo.clearData();
File _image = File(image.path);
photo.addOriginal(_image);
} else {
print('no image selected');
}
} on PlatformException catch (e) {
print('Platform exception $e');
} catch (e) {
print('Unknown error: $e');
}
}
In the android emulator, everything works fine. In the iOS simulator I am able to choose an image, but if I try to choose a second image then the app crashes and 'Lost connection to device.' is printed in the run tab - but no errors.
Question: How can I fix this so that I can go back to the gallery and select a different image as many times as I want on iOS?
When debugging I have come across this:
PlatformException(multiple_request, Cancelled by a second request, null, null)
I have gone through as many similar questions as I can find on here, GitHub etc... I have:
upgraded flutter
upgraded pub files
flutter clean
clean and build in Xcode
added 'imageCache.clear()' in flutter code
invalidate caches and restart in android studio
flutter doctor -v : no issues found
checked the permissions (info.plist and added permission_handler package)
restarted the simulator
erased all contents and settings in simulator
debugging with breakpoints weirdly stops the problem from happening a few times then after a few selections the app crashes again ¯\(ツ)/¯
I'm sure its something straight forward but I feel like I have exhausted all my options and not sure where to go from here.
Your code is right and it is a simulator problem,if you want to test it on IOS, you have to test on a real IPhone and here is a snippet on how properly you can do it:
final imagePicker = ImagePicker();
PickedFile pickedFile;
if (fileType == FileType.Camera) {
// Camera Part
pickedFile = await imagePicker.getImage(
source: ImageSource.camera,
maxWidth: 480,
maxHeight: 640,
imageQuality: 25, // pick your desired quality
);
setState(() {
if (pickedFile != null) {
_storedFile = File(pickedFile.path);
} else {
print('No image selected.');
return;
}
});
} else if (fileType == FileType.Gallery) {
// Gallery Part
pickedFile = await imagePicker.getImage(
source: ImageSource.gallery,
maxWidth: 480,
maxHeight: 640,
imageQuality: 25,
);
} else {
print('No image selected.');
return;
}
});
}
and don't forget the enum when the user picks the way he wants to get the image:
enum FileType {
Gallery,
Camera,
Video,
}
Edit:
whenever you add a package that depends on native code, you should restart the whole app build b stopping your build and restarting it again so the native code compiles well, don't forget to restart before putting this package in your pubspec.yaml
Hope it helps, if this answer helped you, don't forget to mark as answered and upvote it please.
since my iPhone Simulator has no camera, it is impossible to debug this on my simulator. But I have a physical device, however, with those stupid provisioning profiles, I am only able to send release versions to my actual iPhone 7, which means it doesnt return debug info.
However, with the help of TRY CATCH I was able to pinpoint when the actual iPhone crashes: it is this line of code:
file = await CrossMedia.Current.TakePhotoAsync(new Plugin.Media.Abstractions.StoreCameraMediaOptions
{
Directory = "Sample",
Name = "test.jpg"
});
The whole code looks like this:
await CrossMedia.Current.Initialize();
Plugin.Media.Abstractions.MediaFile file = null;
try
{
file = await CrossMedia.Current.TakePhotoAsync(new Plugin.Media.Abstractions.StoreCameraMediaOptions
{
Directory = "Sample",
Name = "test.jpg"
});
}
catch
{
await DisplayAlert("1", ":( No camera available.", "OK");
}
if (!CrossMedia.Current.IsCameraAvailable || !CrossMedia.Current.IsTakePhotoSupported)
{
await DisplayAlert("No Camera", ":( No camera available.", "OK");
return;
}
if (file == null)
return;
Since it runs into the catch block here, I know it is the abolev line that throws the error.
This is the james montamagno plugin.
Can you guys help me out here? Might this be a permission problem?
Thank you!
Adding this to info.plist:
<key>NSCameraUsageDescription</key>
<string>This app needs access to the camera to take photos.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>This app needs access to photos.</string>
Solved the issue!