Anonymous
Мое приложение не может безопасно записано видео на Android 14
Сообщение
Anonymous » 05 окт 2025, 13:42
Полная ссылка на проект:
https://github.com/rdtmaster/camcam > Контекст: я разрабатываю приложение, которое позволяет пользователю выбирать камеру (спереди/сзади), выберите фигуру (круг или прямоугольник), затем открываю предварительный просмотр камеры и нарисовать желаемую фигуру выше, а также позволяет пользователю начать/остановить, что на рисунке не визуализируется. Однако я борюсь с сохраненной записанной видео -части. Вот несколько соответствующих фрагментов кода: < /p>
Код: Выделить всё
...
< /code>
//lib/main.lib
import 'package:flutter/material.dart';
import 'package:camera/camera.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:android_intent_plus/android_intent.dart';
import 'package:android_intent_plus/flag.dart';
Future saveVideoToGallery(String videoPath) async {
final fileName = videoPath.split('/').last;
final videoFile = File(videoPath);
if (await Permission.manageExternalStorage.isGranted) {
try {
final mediaStoreUri = Uri.parse('content://media/external/video/media');
final intent = AndroidIntent(
action: 'android.intent.action.MEDIA_SCANNER_SCAN_FILE',
data: 'file://$videoPath',
);
await intent.launch();
} catch (e) {
print('Error while scanning media: $e');
}
} else {
print('Permission denied to manage external storage');
}
}
//...
class _CameraPreviewScreenState extends State {
late CameraController _controller;
late Future _initializeControllerFuture;
bool isRecording = false;
late String videoPath;
@override
void initState() {
super.initState();
_controller = CameraController(widget.camera, ResolutionPreset.high);
_initializeControllerFuture = _controller.initialize();
_requestPermissions();
}
Future _requestPermissions() async {
Map statuses = await [
Permission.camera,
Permission.microphone,
Permission.photos, // Request media access on Android 13+
Permission.videos, // For video media access on Android 13+
].request();
if (await Permission.camera.isPermanentlyDenied ||
await Permission.microphone.isPermanentlyDenied ||
await Permission.photos.isPermanentlyDenied ||
await Permission.videos.isPermanentlyDenied) {
await openAppSettings();
}
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
Future _toggleRecording() async {
try {
// Check if all required permissions are granted
bool hasPermissions = await Permission.camera.isGranted &&
await Permission.microphone.isGranted &&
(await Permission.storage.isGranted ||
await Permission.photos.isGranted);
if (!hasPermissions) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Please grant camera, microphone, and storage permissions')),
);
await _requestPermissions();
return;
}
if (isRecording) {
final file = await _controller.stopVideoRecording();
setState(() {
isRecording = false;
videoPath = file.path;
});
if (Platform.isAndroid) {
// Request Manage External Storage permission for Android 11 and above
await Permission.manageExternalStorage.request();
}
await saveVideoToGallery(videoPath);
} else {
final directory = await getTemporaryDirectory(); // Use temporary directory
final videoFile = '${directory.path}/${DateTime.now().millisecondsSinceEpoch}.mp4';
await _controller.startVideoRecording();
setState(() {
isRecording = true;
videoPath = videoFile;
});
}
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Error during recording: $e')),
);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: FutureBuilder(
future: _initializeControllerFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
return Stack(
fit: StackFit.expand,
children: [
CameraPreview(_controller),
CustomPaint(
painter: FigurePainter(figureData: widget.figureData),
),
Positioned(
bottom: 20,
right: 20,
child: IconButton(
icon: Icon(
isRecording ? Icons.stop : Icons.videocam,
color: Colors.red,
size: 50,
),
onPressed: _toggleRecording,
),
),
],
);
} else {
return const Center(child: CircularProgressIndicator());
}
},
),
);
}
}
//...
< /code>
Как вы можете увидеть, я пробую все, чтобы запросить разрешения, но всякий раз, когда я нажимаю кнопку записи, он показывает законечную бабуру о предоставлении разрешений (и не появляется система системы Android). Разрешения на камеру и микрофона запрашиваются, как только кнопка Open нажата, а также они находятся под настройками приложения, однако нет разрешений, связанных с файлами, что также кажется тревожным.
Подробнее здесь:
https://stackoverflow.com/questions/797 ... android-14
1759660929
Anonymous
Полная ссылка на проект: https://github.com/rdtmaster/camcam> Контекст: я разрабатываю приложение, которое позволяет пользователю выбирать камеру (спереди/сзади), выберите фигуру (круг или прямоугольник), затем открываю предварительный просмотр камеры и нарисовать желаемую фигуру выше, а также позволяет пользователю начать/остановить, что на рисунке не визуализируется. Однако я борюсь с сохраненной записанной видео -части. Вот несколько соответствующих фрагментов кода: < /p> [code] ... < /code> //lib/main.lib import 'package:flutter/material.dart'; import 'package:camera/camera.dart'; import 'package:path_provider/path_provider.dart'; import 'package:permission_handler/permission_handler.dart'; import 'package:android_intent_plus/android_intent.dart'; import 'package:android_intent_plus/flag.dart'; Future saveVideoToGallery(String videoPath) async { final fileName = videoPath.split('/').last; final videoFile = File(videoPath); if (await Permission.manageExternalStorage.isGranted) { try { final mediaStoreUri = Uri.parse('content://media/external/video/media'); final intent = AndroidIntent( action: 'android.intent.action.MEDIA_SCANNER_SCAN_FILE', data: 'file://$videoPath', ); await intent.launch(); } catch (e) { print('Error while scanning media: $e'); } } else { print('Permission denied to manage external storage'); } } //... class _CameraPreviewScreenState extends State { late CameraController _controller; late Future _initializeControllerFuture; bool isRecording = false; late String videoPath; @override void initState() { super.initState(); _controller = CameraController(widget.camera, ResolutionPreset.high); _initializeControllerFuture = _controller.initialize(); _requestPermissions(); } Future _requestPermissions() async { Map statuses = await [ Permission.camera, Permission.microphone, Permission.photos, // Request media access on Android 13+ Permission.videos, // For video media access on Android 13+ ].request(); if (await Permission.camera.isPermanentlyDenied || await Permission.microphone.isPermanentlyDenied || await Permission.photos.isPermanentlyDenied || await Permission.videos.isPermanentlyDenied) { await openAppSettings(); } } @override void dispose() { _controller.dispose(); super.dispose(); } Future _toggleRecording() async { try { // Check if all required permissions are granted bool hasPermissions = await Permission.camera.isGranted && await Permission.microphone.isGranted && (await Permission.storage.isGranted || await Permission.photos.isGranted); if (!hasPermissions) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Please grant camera, microphone, and storage permissions')), ); await _requestPermissions(); return; } if (isRecording) { final file = await _controller.stopVideoRecording(); setState(() { isRecording = false; videoPath = file.path; }); if (Platform.isAndroid) { // Request Manage External Storage permission for Android 11 and above await Permission.manageExternalStorage.request(); } await saveVideoToGallery(videoPath); } else { final directory = await getTemporaryDirectory(); // Use temporary directory final videoFile = '${directory.path}/${DateTime.now().millisecondsSinceEpoch}.mp4'; await _controller.startVideoRecording(); setState(() { isRecording = true; videoPath = videoFile; }); } } catch (e) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Error during recording: $e')), ); } } @override Widget build(BuildContext context) { return Scaffold( body: FutureBuilder( future: _initializeControllerFuture, builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.done) { return Stack( fit: StackFit.expand, children: [ CameraPreview(_controller), CustomPaint( painter: FigurePainter(figureData: widget.figureData), ), Positioned( bottom: 20, right: 20, child: IconButton( icon: Icon( isRecording ? Icons.stop : Icons.videocam, color: Colors.red, size: 50, ), onPressed: _toggleRecording, ), ), ], ); } else { return const Center(child: CircularProgressIndicator()); } }, ), ); } } //... < /code> Как вы можете увидеть, я пробую все, чтобы запросить разрешения, но всякий раз, когда я нажимаю кнопку записи, он показывает законечную бабуру о предоставлении разрешений (и не появляется система системы Android). Разрешения на камеру и микрофона запрашиваются, как только кнопка Open [/code] нажата, а также они находятся под настройками приложения, однако нет разрешений, связанных с файлами, что также кажется тревожным. Подробнее здесь: [url]https://stackoverflow.com/questions/79782929/my-app-is-unable-to-safe-recorded-video-on-android-14[/url]