Я постоянно получаю следующее исключение во Flutter, когда пытаюсь открыть ReaderWidget этого примера из библиотеки zxing:
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: CameraException(channel-error, Unable to establish connection on channel: "dev.flutter.pigeon.camera_avfoundation.CameraApi.getAvailableCameras".)
#0 AVFoundationCamera.availableCameras (package:camera_avfoundation/src/avfoundation_camera.dart:76:7)
#1 _ReaderWidgetState.initStateAsync. (package:flutter_zxing/src/ui/reader_widget.dart:199:29)
Следующая часть выдает исключение (ссылка на пакет на github):
@override
Future availableCameras() async {
try {
return (await _hostApi.getAvailableCameras())
// See comment in messages.dart for why this is safe.
.map((PlatformCameraDescription? c) => c!)
.map(cameraDescriptionFromPlatform)
.toList();
} on PlatformException catch (e) {
throw CameraException(e.code, e.message);
}
}
Аналогичное исключение возникает, когда я пытаюсь получить доступ к медиатеке.
Я обнаружил, что мне нужно добавить следующие строки в info.plist, что я и сделал:
NSPhotoLibraryUsageDescription
We need photo library access to scan barcodes
NSCameraUsageDescription
We need to access your camera for scanning QR codes
Когда я открываю XCode -> Runner -> Runner -> Info, я также вижу перечисленные записи и послесловия, которые я успешно выполнил, флаттер сборки ios.
Кроме того, при использовании приложения мне никогда не предлагается предоставить доступ. Я просто открываю экран, где должна быть камера, и вижу ошибку.
Когда я скачиваю и устанавливаю пример, все работает как положено. Появляется всплывающее окно, и я вижу опцию «Камера» в настройках приложения на моем телефоне. Я также пробовал скопировать Info.plist из примера 1:1, но это тоже не помогает.
Есть идеи, как заставить работать разрешения или какие дополнительные шаги Мне нужно запросить разрешение?
Вот код моего компонента:
class SetupStepScanQrCode extends StatefulWidget {
final SetupStepperWidget setupStepper;
const SetupStepScanQrCode(this.setupStepper, {Key? key}) : super(key: key);
@override
State createState() => SetupStepScanQrCodeState();
}
class SetupStepScanQrCodeState extends State {
late final SetupStepperWidget setupStepper;
Uint8List? createdCodeBytes;
Code? result;
Codes? multiResult;
bool isMultiScan = false;
bool showDebugInfo = true;
int successScans = 0;
int failedScans = 0;
bool isManualProcess = false;
bool qrCodeScanned = false;
String? deviceName;
String? devicePassword;
@override
void initState() {
super.initState();
setupStepper = widget.setupStepper;
}
void setDeviceDetails(name, password) {
deviceName = name;
devicePassword = password;
}
void connect() {
setupStepper.setDeviceDetails(deviceName, devicePassword);
setupStepper.next();
}
Future _initializeReaderWidget() async {
try {
return ReaderWidget(
onScan: _onScanSuccess,
onScanFailure: _onScanFailure,
onMultiScan: _onMultiScanSuccess,
onMultiScanFailure: _onMultiScanFailure,
onMultiScanModeChanged: _onMultiScanModeChanged,
onControllerCreated: _onControllerCreated,
isMultiScan: isMultiScan,
scanDelay: Duration(milliseconds: isMultiScan ? 50 : 500),
resolution: ResolutionPreset.high,
lensDirection: CameraLensDirection.back,
flashOnIcon: const Icon(Icons.flash_on),
flashOffIcon: const Icon(Icons.flash_off),
flashAlwaysIcon: const Icon(Icons.flash_on),
flashAutoIcon: const Icon(Icons.flash_auto),
galleryIcon: const Icon(Icons.photo_library),
toggleCameraIcon: const Icon(Icons.switch_camera),
actionButtonsBackgroundBorderRadius: BorderRadius.circular(10),
actionButtonsBackgroundColor: Colors.black.withOpacity(0.5),
);
} catch (e) {
print(e);
return Center(child: Text('Error initializing camera (caught).'));
}
}
@override
Widget build(BuildContext context) {
final isCameraSupported = defaultTargetPlatform == TargetPlatform.iOS ||
defaultTargetPlatform == TargetPlatform.android;
return BaseLayout(
stepTitle,
SizedBox(
height: 300,
width: 300,
child: Stack(
children: [
FutureBuilder(
future: _initializeReaderWidget(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasError) {
// Display error message or a fallback UI
return Center(
child: Text(
'Error initializing camera (snapshot.hasError)'));
}
// Return the ReaderWidget or error widget if no error
return snapshot.data!;
} else {
// Return a loading indicator while waiting for the future to complete
return Center(child: CircularProgressIndicator());
}
},
),
if (showDebugInfo)
DebugInfoWidget(
successScans: successScans,
failedScans: failedScans,
error: isMultiScan ? multiResult?.error : result?.error,
duration: isMultiScan
? multiResult?.duration ?? 0
: result?.duration ?? 0,
onReset: _onReset,
),
],
),
),
description: stepDescription,
content: Column(
children: stepContent,
),
);
}
String get stepTitle {
if (isManualProcess) {
return 'Bluetoothverbindung herstellen';
}
return 'Scan QR-Code';
}
String get stepImage {
if (isManualProcess) {
return manualSetupBluetooth;
}
return cameraPlaceholder;
}
String get stepDescription {
if (isManualProcess) {
return '';
}
return 'Hier eine Anleitung.';
}
List get stepContent {
if (isManualProcess) {
return [SetupStepSubBluetooth(this)];
}
return [
qrCodeScanned
? Text(
'QR-Code erkannt',
textAlign: TextAlign.center,
style: Theme.of(context)
.textTheme
.displayMedium!
.copyWith(color: Theme.of(context).colorScheme.primary),
)
: Text(
'Kein QR-Code vorhanden?',
textAlign: TextAlign.center,
style: Theme.of(context)
.textTheme
.displaySmall!
.copyWith(color: const Color(0xFF7C7C7C)),
),
SizedBox(height: qrCodeScanned ? paddingMain * 2 : paddingMain / 2),
qrCodeScanned
? FilledButton(
onPressed: () {
// TODO: Disable if devicename and password are empty
connect();
},
child: const Text('Jetzt verbinden'),
)
: OutlinedButton(
onPressed: () {
setState(() {
isManualProcess = true;
});
},
child: const Text('Manuelle Eingabe starten'),
),
];
}
void _onControllerCreated(_, Exception? error) {
if (error != null) {
// Handle permission or unknown errors
_showMessage(context, 'Error: $error');
}
}
_onScanSuccess(Code? code) {
setState(() {
successScans++;
result = code;
});
}
_onScanFailure(Code? code) {
setState(() {
failedScans++;
result = code;
});
if (code?.error?.isNotEmpty == true) {
_showMessage(context, 'Error: ${code?.error}');
}
}
_onMultiScanSuccess(Codes codes) {
setState(() {
successScans++;
multiResult = codes;
});
}
_onMultiScanFailure(Codes result) {
setState(() {
failedScans++;
multiResult = result;
});
if (result.codes.isNotEmpty == true) {
_showMessage(context, 'Error: ${result.codes.first.error}');
}
}
_onMultiScanModeChanged(bool isMultiScan) {
setState(() {
this.isMultiScan = isMultiScan;
});
}
_showMessage(BuildContext context, String message) {
ScaffoldMessenger.of(context).hideCurrentSnackBar();
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(message)),
);
}
_onReset() {
setState(() {
successScans = 0;
failedScans = 0;
});
}
}
Вот мой Info.plist (который - согласно XCode -> Targets Runner -> Настройки сборки -> Файл Info.plist используется при отладке, профилировании и выпуске)
CADisableMinimumFrameDurationOnPhone
CFBundleDevelopmentRegion
$(DEVELOPMENT_LANGUAGE)
CFBundleDisplayName
COMPANY Myapplication
CFBundleExecutable
$(EXECUTABLE_NAME)
CFBundleIdentifier
$(PRODUCT_BUNDLE_IDENTIFIER)
CFBundleInfoDictionaryVersion
6.0
CFBundleName
myapplication
CFBundlePackageType
APPL
CFBundleShortVersionString
$(FLUTTER_BUILD_NAME)
CFBundleSignature
????
CFBundleURLTypes
CFBundleTypeRole
Editor
CFBundleURLName
auth0
CFBundleURLSchemes
$(PRODUCT_BUNDLE_IDENTIFIER)
CFBundleVersion
$(FLUTTER_BUILD_NUMBER)
LSRequiresIPhoneOS
NSBluetoothAlwaysUsageDescription
Our app uses Bluetooth to configure your WiFi credentials.
UIApplicationSupportsIndirectInputEvents
UILaunchStoryboardName
LaunchScreen
UIMainStoryboardFile
Main
NSPhotoLibraryUsageDescription
We need photo library access to scan barcodes
NSCameraUsageDescription
We need to access your camera for scanning QR codes
UISupportedInterfaceOrientations
UIInterfaceOrientationPortrait
UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight
UISupportedInterfaceOrientations~ipad
UIInterfaceOrientationPortrait
UIInterfaceOrientationPortraitUpsideDown
UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight
Подробнее здесь: https://stackoverflow.com/questions/786 ... er-project
Исключение разрешения камеры на iOS в проекте флаттера ⇐ IOS
Программируем под IOS
-
Anonymous
1719920986
Anonymous
Я постоянно получаю следующее исключение во Flutter, когда пытаюсь открыть ReaderWidget этого примера из библиотеки zxing:
[ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: CameraException(channel-error, Unable to establish connection on channel: "dev.flutter.pigeon.camera_avfoundation.CameraApi.getAvailableCameras".)
#0 AVFoundationCamera.availableCameras (package:camera_avfoundation/src/avfoundation_camera.dart:76:7)
#1 _ReaderWidgetState.initStateAsync. (package:flutter_zxing/src/ui/reader_widget.dart:199:29)
Следующая часть выдает исключение (ссылка на пакет на github):
@override
Future availableCameras() async {
try {
return (await _hostApi.getAvailableCameras())
// See comment in messages.dart for why this is safe.
.map((PlatformCameraDescription? c) => c!)
.map(cameraDescriptionFromPlatform)
.toList();
} on PlatformException catch (e) {
throw CameraException(e.code, e.message);
}
}
Аналогичное исключение возникает, когда я пытаюсь получить доступ к медиатеке.
Я обнаружил, что мне нужно добавить следующие строки в info.plist, что я и сделал:
NSPhotoLibraryUsageDescription
We need photo library access to scan barcodes
NSCameraUsageDescription
We need to access your camera for scanning QR codes
Когда я открываю XCode -> Runner -> Runner -> Info, я также вижу перечисленные записи и послесловия, которые я успешно выполнил, флаттер сборки ios.
Кроме того, при использовании приложения мне никогда не предлагается предоставить доступ. Я просто открываю экран, где должна быть камера, и вижу ошибку.
Когда я скачиваю и устанавливаю пример, все работает как положено. Появляется всплывающее окно, и я вижу опцию «Камера» в настройках приложения на моем телефоне. Я также пробовал скопировать Info.plist из примера 1:1, но это тоже не помогает.
Есть идеи, как заставить работать разрешения или какие дополнительные шаги Мне нужно запросить разрешение?
Вот код моего компонента:
class SetupStepScanQrCode extends StatefulWidget {
final SetupStepperWidget setupStepper;
const SetupStepScanQrCode(this.setupStepper, {Key? key}) : super(key: key);
@override
State createState() => SetupStepScanQrCodeState();
}
class SetupStepScanQrCodeState extends State {
late final SetupStepperWidget setupStepper;
Uint8List? createdCodeBytes;
Code? result;
Codes? multiResult;
bool isMultiScan = false;
bool showDebugInfo = true;
int successScans = 0;
int failedScans = 0;
bool isManualProcess = false;
bool qrCodeScanned = false;
String? deviceName;
String? devicePassword;
@override
void initState() {
super.initState();
setupStepper = widget.setupStepper;
}
void setDeviceDetails(name, password) {
deviceName = name;
devicePassword = password;
}
void connect() {
setupStepper.setDeviceDetails(deviceName, devicePassword);
setupStepper.next();
}
Future _initializeReaderWidget() async {
try {
return ReaderWidget(
onScan: _onScanSuccess,
onScanFailure: _onScanFailure,
onMultiScan: _onMultiScanSuccess,
onMultiScanFailure: _onMultiScanFailure,
onMultiScanModeChanged: _onMultiScanModeChanged,
onControllerCreated: _onControllerCreated,
isMultiScan: isMultiScan,
scanDelay: Duration(milliseconds: isMultiScan ? 50 : 500),
resolution: ResolutionPreset.high,
lensDirection: CameraLensDirection.back,
flashOnIcon: const Icon(Icons.flash_on),
flashOffIcon: const Icon(Icons.flash_off),
flashAlwaysIcon: const Icon(Icons.flash_on),
flashAutoIcon: const Icon(Icons.flash_auto),
galleryIcon: const Icon(Icons.photo_library),
toggleCameraIcon: const Icon(Icons.switch_camera),
actionButtonsBackgroundBorderRadius: BorderRadius.circular(10),
actionButtonsBackgroundColor: Colors.black.withOpacity(0.5),
);
} catch (e) {
print(e);
return Center(child: Text('Error initializing camera (caught).'));
}
}
@override
Widget build(BuildContext context) {
final isCameraSupported = defaultTargetPlatform == TargetPlatform.iOS ||
defaultTargetPlatform == TargetPlatform.android;
return BaseLayout(
stepTitle,
SizedBox(
height: 300,
width: 300,
child: Stack(
children: [
FutureBuilder(
future: _initializeReaderWidget(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasError) {
// Display error message or a fallback UI
return Center(
child: Text(
'Error initializing camera (snapshot.hasError)'));
}
// Return the ReaderWidget or error widget if no error
return snapshot.data!;
} else {
// Return a loading indicator while waiting for the future to complete
return Center(child: CircularProgressIndicator());
}
},
),
if (showDebugInfo)
DebugInfoWidget(
successScans: successScans,
failedScans: failedScans,
error: isMultiScan ? multiResult?.error : result?.error,
duration: isMultiScan
? multiResult?.duration ?? 0
: result?.duration ?? 0,
onReset: _onReset,
),
],
),
),
description: stepDescription,
content: Column(
children: stepContent,
),
);
}
String get stepTitle {
if (isManualProcess) {
return 'Bluetoothverbindung herstellen';
}
return 'Scan QR-Code';
}
String get stepImage {
if (isManualProcess) {
return manualSetupBluetooth;
}
return cameraPlaceholder;
}
String get stepDescription {
if (isManualProcess) {
return '';
}
return 'Hier eine Anleitung.';
}
List get stepContent {
if (isManualProcess) {
return [SetupStepSubBluetooth(this)];
}
return [
qrCodeScanned
? Text(
'QR-Code erkannt',
textAlign: TextAlign.center,
style: Theme.of(context)
.textTheme
.displayMedium!
.copyWith(color: Theme.of(context).colorScheme.primary),
)
: Text(
'Kein QR-Code vorhanden?',
textAlign: TextAlign.center,
style: Theme.of(context)
.textTheme
.displaySmall!
.copyWith(color: const Color(0xFF7C7C7C)),
),
SizedBox(height: qrCodeScanned ? paddingMain * 2 : paddingMain / 2),
qrCodeScanned
? FilledButton(
onPressed: () {
// TODO: Disable if devicename and password are empty
connect();
},
child: const Text('Jetzt verbinden'),
)
: OutlinedButton(
onPressed: () {
setState(() {
isManualProcess = true;
});
},
child: const Text('Manuelle Eingabe starten'),
),
];
}
void _onControllerCreated(_, Exception? error) {
if (error != null) {
// Handle permission or unknown errors
_showMessage(context, 'Error: $error');
}
}
_onScanSuccess(Code? code) {
setState(() {
successScans++;
result = code;
});
}
_onScanFailure(Code? code) {
setState(() {
failedScans++;
result = code;
});
if (code?.error?.isNotEmpty == true) {
_showMessage(context, 'Error: ${code?.error}');
}
}
_onMultiScanSuccess(Codes codes) {
setState(() {
successScans++;
multiResult = codes;
});
}
_onMultiScanFailure(Codes result) {
setState(() {
failedScans++;
multiResult = result;
});
if (result.codes.isNotEmpty == true) {
_showMessage(context, 'Error: ${result.codes.first.error}');
}
}
_onMultiScanModeChanged(bool isMultiScan) {
setState(() {
this.isMultiScan = isMultiScan;
});
}
_showMessage(BuildContext context, String message) {
ScaffoldMessenger.of(context).hideCurrentSnackBar();
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(message)),
);
}
_onReset() {
setState(() {
successScans = 0;
failedScans = 0;
});
}
}
Вот мой Info.plist (который - согласно XCode -> Targets Runner -> Настройки сборки -> Файл Info.plist используется при отладке, профилировании и выпуске)
CADisableMinimumFrameDurationOnPhone
CFBundleDevelopmentRegion
$(DEVELOPMENT_LANGUAGE)
CFBundleDisplayName
COMPANY Myapplication
CFBundleExecutable
$(EXECUTABLE_NAME)
CFBundleIdentifier
$(PRODUCT_BUNDLE_IDENTIFIER)
CFBundleInfoDictionaryVersion
6.0
CFBundleName
myapplication
CFBundlePackageType
APPL
CFBundleShortVersionString
$(FLUTTER_BUILD_NAME)
CFBundleSignature
????
CFBundleURLTypes
CFBundleTypeRole
Editor
CFBundleURLName
auth0
CFBundleURLSchemes
$(PRODUCT_BUNDLE_IDENTIFIER)
CFBundleVersion
$(FLUTTER_BUILD_NUMBER)
LSRequiresIPhoneOS
NSBluetoothAlwaysUsageDescription
Our app uses Bluetooth to configure your WiFi credentials.
UIApplicationSupportsIndirectInputEvents
UILaunchStoryboardName
LaunchScreen
UIMainStoryboardFile
Main
NSPhotoLibraryUsageDescription
We need photo library access to scan barcodes
NSCameraUsageDescription
We need to access your camera for scanning QR codes
UISupportedInterfaceOrientations
UIInterfaceOrientationPortrait
UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight
UISupportedInterfaceOrientations~ipad
UIInterfaceOrientationPortrait
UIInterfaceOrientationPortraitUpsideDown
UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight
Подробнее здесь: [url]https://stackoverflow.com/questions/78650742/camera-permission-exception-on-ios-in-flutter-project[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия