Untitled
unknown
plain_text
a year ago
9.2 kB
7
Indexable
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:camera/camera.dart';
import 'package:path_provider/path_provider.dart';
import 'package:video_compress/video_compress.dart';
import 'package:gal/gal.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:device_info_plus/device_info_plus.dart';
class CameraScreen extends StatefulWidget {
@override
_CameraScreenState createState() => _CameraScreenState();
}
class _CameraScreenState extends State<CameraScreen> {
CameraController? _controller;
late Future<void> _initializeControllerFuture;
bool _isRecording = false;
String? _recordedVideoPath;
double _compressionProgress = 0.0;
late Subscription _subscription;
bool _cameraInitialized = false;
String? _errorMessage;
@override
void initState() {
super.initState();
_subscription = VideoCompress.compressProgress$.subscribe((progress) {
setState(() {
_compressionProgress = progress;
});
debugPrint('Compression progress: $progress');
});
_initializeControllerFuture = _initializeCamera();
_requestCameraPermission();
}
Future<void> _requestCameraPermission() async {
final status = await Permission.camera.request();
debugPrint('Camera permission status: ${status.isGranted}');
}
Future<void> _initializeCamera() async {
try {
debugPrint('[DEBUG] Requesting camera permission...');
final cameraPermissionStatus = await Permission.camera.request();
debugPrint('[DEBUG] Camera permission status: ${cameraPermissionStatus.isGranted}');
if (!cameraPermissionStatus.isGranted) {
_showPermissionDeniedDialog(context);
return;
}
debugPrint('[DEBUG] Fetching available cameras...');
final cameras = await availableCameras();
debugPrint('[DEBUG] Available cameras: $cameras');
if (cameras.isEmpty) {
setState(() {
_errorMessage = 'No cameras available';
});
return;
}
final firstCamera = cameras.first;
debugPrint('[DEBUG] Initializing camera controller with: $firstCamera');
_controller = CameraController(firstCamera, ResolutionPreset.high);
await _controller?.initialize();
if (!mounted) {
return;
}
setState(() {
_cameraInitialized = true;
});
debugPrint('[DEBUG] Camera initialized successfully');
} catch (e) {
debugPrint('[DEBUG] Failed to initialize camera: $e');
setState(() {
_errorMessage = 'Failed to initialize camera: $e';
});
}
}
void _checkPermissionStatus() async {
final status = await Permission.camera.status;
debugPrint('[DEBUG] Camera permission status (programmatic check): ${status.isGranted}');
}
@override
void dispose() {
_controller?.dispose();
_subscription.unsubscribe();
super.dispose();
}
Future<void> _compressAndSaveVideo(String videoPath) async {
print('[DEBUG] Compressing video...');
final info = await VideoCompress.compressVideo(
videoPath,
quality: VideoQuality.MediumQuality,
deleteOrigin: false, // Set to true if you want to delete the original video
);
if (info != null && info.file != null) {
final compressedVideoPath = info.file!.path;
print('[DEBUG] Video compressed to $compressedVideoPath');
await _saveVideoToGallery(compressedVideoPath);
} else {
print('[DEBUG] Video compression failed');
}
}
Future<void> _saveVideoToGallery(String videoPath) async {
if (await _requestStoragePermission()) {
print('[DEBUG] Saving video to gallery...');
final result = await Gal.putVideo(videoPath);
print('[DEBUG] Save result');
} else {
print('[DEBUG] Storage permission denied');
}
}
Future<bool> _requestStoragePermission() async {
if (Platform.isIOS) {
final status = await Permission.photos.request();
debugPrint('[DEBUG] iOS storage permission status: ${status.isGranted}');
return status.isGranted;
} else {
DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
AndroidDeviceInfo androidInfo = await deviceInfo.androidInfo;
if (androidInfo.version.sdkInt >= 30) {
final status = await Permission.manageExternalStorage.request();
debugPrint('[DEBUG] Android (SDK >= 30) storage permission status: ${status.isGranted}');
return status.isGranted;
} else {
final status = await Permission.storage.request();
debugPrint('[DEBUG] Android (SDK < 30) storage permission status: ${status.isGranted}');
return status.isGranted;
}
}
}
Future<String> _getVideoPath() async {
final directory = await getApplicationDocumentsDirectory();
final videoDir = Directory('${directory.path}/video_compress');
if (!await videoDir.exists()) {
await videoDir.create(recursive: true);
}
return videoDir.path;
}
void _showPermissionDeniedDialog(BuildContext context) {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text('Permission Denied'),
content: Text('Camera permission is required to use this feature. Please enable it in the app settings.'),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: Text('Cancel'),
),
TextButton(
onPressed: () {
openAppSettings();
},
child: Text('Open Settings'),
),
],
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Take Video'),
leading: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () {
context.go('/home'); // Navigate back
},
),
),
body: FutureBuilder<void>(
future: _initializeControllerFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (_errorMessage != null) {
return Center(
child: Text(_errorMessage!),
);
}
return Stack(
children: [
_controller == null
? Center(child: Text('Camera not available'))
: CameraPreview(_controller!),
if (_compressionProgress > 0.0 && _compressionProgress < 100.0)
Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
CircularProgressIndicator(
value: _compressionProgress,
),
const SizedBox(height: 10),
Text(
'${(_compressionProgress * 100).toStringAsFixed(1)}%',
style: const TextStyle(fontSize: 20),
),
],
),
),
],
);
} else if (snapshot.hasError) {
return Center(
child: Text('Error initializing camera: ${snapshot.error}'),
);
} else {
return Center(child: CircularProgressIndicator());
}
},
),
floatingActionButton: FutureBuilder<void>(
future: _initializeControllerFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done && _controller != null && _controller!.value.isInitialized) {
return FloatingActionButton(
onPressed: () async {
if (_controller != null && _controller!.value.isInitialized) {
try {
if (!_isRecording) {
final videoPath = await _getVideoPath();
_recordedVideoPath = '$videoPath/recorded_video.mp4';
await _controller!.startVideoRecording();
setState(() {
_isRecording = true;
});
print('[DEBUG] Recording started...');
} else {
final video = await _controller!.stopVideoRecording();
setState(() {
_isRecording = false;
});
print('[DEBUG] Recording stopped. Video saved at ${video.path}');
if (_recordedVideoPath != null) {
await _compressAndSaveVideo(video.path);
}
}
} catch (e) {
print('[DEBUG] Error: $e');
}
}
},
child: Icon(_isRecording ? Icons.stop : Icons.videocam),
);
} else {
return Container(); // Or an alternative placeholder
}
},
),
);
}
}
Editor is loading...
Leave a Comment