Flutter原生相机功能插件lecle_native_camera的使用
Flutter原生相机功能插件lecle_native_camera的使用
lecle_native_camera
是一个用于在Flutter项目中打开设备摄像头以拍摄照片或视频(在Android平台上也可以选择照片)并在Android和iOS平台上获取文件路径和文件类型的插件。
Android
在 AndroidManifest.xml
文件中添加以下属性:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="your package...">
添加以下权限:
<uses-feature android:name="android.hardware.camera.any"
android:required="true" />
<uses-feature android:name="android.hardware.camera.autofocus"
android:required="false" />
<uses-permission android:name="android.permission.CAMERA"
android:required="true"
android:requiredFeature="true" />
<uses-permission android:name="android.permission.FLASHLIGHT" />
<uses-feature android:name="android.hardware.camera.flash" android:required="false"
tools:targetApi="eclair" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
在 android/app/src/main/res
目录下创建 xml
文件夹,并添加以下内容到 file_paths.xml
文件:
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name="external_files"
path="." />
</paths>
创建自己的 FileProvider
并定义自己的路径,然后将其添加到 AndroidManifest.xml
文件中:
<provider android:name="androidx.core.content.FileProvider"
android:authorities="vn.lecle.native_camera.fileprovider"
android:exported="false" android:grantUriPermissions="true">
<meta-data android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
iOS
在 Info.plist
文件中添加以下内容:
<key>NSCameraUsageDescription</key>
<string>我们的应用需要访问您的摄像头</string>
<key>NSMicrophoneUsageDescription</key>
<string>$(PRODUCT_NAME) 需要访问麦克风以录制视频和音频</string>
<key>NSPhotoLibraryAddUsageDescription</key>
<string>$(PRODUCT_NAME) 需要保存照片到您的相册</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>$(PRODUCT_NAME) 需要访问您的照片</string>
<key>NSBonjourServices</key>
<array>
<string>_dartobservatory._tcp</string>
</array>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
如何使用
只需调用 LecleNativeCamera
类中的 openNativeCamera
方法即可打开原生相机以拍摄照片或视频(在Android平台上也可以选择照片),该方法将返回捕获文件的路径和文件类型。
返回的数据将被转换为 FileData
对象,您可以使用此对象轻松获取文件路径和文件类型。
属性
以下是 openNativeCamera
方法中的属性及其适用平台:
属性 | Android | iOS |
---|---|---|
fileProviderPath | X | |
imageExtension | X | X |
videoExtension | X | X |
fileName | X | X |
androidOptionSheetTitle | X | |
canPickFile | X | |
videoQuality | X | X |
imageQuality | X | X |
imageWidth | X | |
imageHeight | X | |
customSaveFolder | X | |
saveFolder | X |
示例
以下是一个完整的示例代码,展示了如何使用 lecle_native_camera
插件来打开原生相机并处理拍摄的照片或视频。
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:lecle_native_camera/constants/enums/enums.dart';
import 'package:lecle_native_camera/lecle_native_camera.dart';
import 'package:lecle_native_camera/models/file_data_model.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:video_player/video_player.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
[@override](/user/override)
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
[@override](/user/override)
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
File? imageFile;
File? videoFile;
VideoPlayerController? _controller;
bool _isPlaying = false;
[@override](/user/override)
void initState() {
super.initState();
_requestPermissions();
}
[@override](/user/override)
void dispose() {
_controller?.dispose();
super.dispose();
}
void _requestPermissions() async {
await [Permission.camera, Permission.microphone, Permission.storage]
.request();
}
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: SingleChildScrollView(
child: SizedBox(
width: MediaQuery.of(context).size.width,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: [
Visibility(
visible: imageFile != null,
child: imageFile != null
? Image.file(imageFile!)
: const SizedBox.shrink(),
),
Visibility(
visible: videoFile != null && _controller != null,
child: videoFile != null && _controller != null
? AspectRatio(
child: VideoPlayer(_controller!),
aspectRatio: _controller!.value.aspectRatio,
)
: const SizedBox.shrink(),
),
const SizedBox(height: 32.0),
ElevatedButton(
onPressed: () async {
if (videoFile == null) {
return;
}
_controller?.value.isPlaying ?? false
? await _controller?.pause()
: await _controller?.play();
if (_controller?.value.isPlaying ?? false) {
setState(() {
_isPlaying = true;
});
} else {
setState(() {
_isPlaying = false;
});
}
},
child: Icon(
_isPlaying ? Icons.pause : Icons.play_arrow,
),
),
ElevatedButton(
onPressed: () {
LecleNativeCamera.openNativeCamera(
fileProviderPath: 'vn.lecle.native_camera.fileprovider', // 这必须与您在AndroidManifest文件中定义的自定义路径相同
imageExtension: ImageExtension.jpeg,
videoQuality: VideoQuality.typeHigh,
videoExtension: VideoExtension.mov,
imageQuality: 100,
imageWidth: 2160,
imageHeight: 3804,
androidOptionSheetTitle: 'Choose an option',
canPickFile: true,
fileName: 'your_custom_file_name',
customSaveFolder: 'Test Folder',
).then(
(value) async {
if (value != null) {
print('$value');
if (value.fileType == FileType.image && value.filePath != null) {
setState(() {
imageFile = File(value.filePath!);
imageFile!.length().then((value) {
print('File size ::: $value');
});
videoFile = null;
_controller = null;
});
} else if (value.fileType == FileType.video && value.filePath != null) {
setState(() {
videoFile = File(value.filePath!);
videoFile!.length().then((value) {
print('File size ::: $value');
});
imageFile = null;
_controller = VideoPlayerController.file(videoFile!);
_controller!.initialize().then(
(value) {
setState(() {});
_controller!.addListener(() {
if (_controller?.value.position == _controller?.value.duration) {
setState(() {
_isPlaying = false;
});
}
});
},
);
});
}
}
},
);
},
child: const Text('Open native camera'),
),
],
),
),
),
);
}
}
更多关于Flutter原生相机功能插件lecle_native_camera的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter原生相机功能插件lecle_native_camera的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
lecle_native_camera
是一个 Flutter 插件,用于在 Flutter 应用中集成原生相机功能。它允许你访问设备的摄像头,并捕获照片或视频。以下是如何使用 lecle_native_camera
插件的基本步骤:
1. 添加依赖
首先,你需要在 pubspec.yaml
文件中添加 lecle_native_camera
插件的依赖:
dependencies:
flutter:
sdk: flutter
lecle_native_camera: ^1.0.0 # 请使用最新的版本号
然后运行 flutter pub get
来安装依赖。
2. 配置权限
为了使用相机功能,你需要在 AndroidManifest.xml
和 Info.plist
中添加相应的权限。
Android
在 android/app/src/main/AndroidManifest.xml
文件中添加以下权限:
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
iOS
在 ios/Runner/Info.plist
文件中添加以下键值对:
<key>NSCameraUsageDescription</key>
<string>We need access to your camera to take photos.</string>
<key>NSMicrophoneUsageDescription</key>
<string>We need access to your microphone to record video.</string>
3. 初始化相机
在你的 Flutter 应用中,你可以通过以下步骤初始化相机:
import 'package:flutter/material.dart';
import 'package:lecle_native_camera/lecle_native_camera.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: CameraScreen(),
);
}
}
class CameraScreen extends StatefulWidget {
@override
_CameraScreenState createState() => _CameraScreenState();
}
class _CameraScreenState extends State<CameraScreen> {
late NativeCameraController _cameraController;
@override
void initState() {
super.initState();
_initializeCamera();
}
Future<void> _initializeCamera() async {
_cameraController = NativeCameraController();
await _cameraController.initialize();
}
@override
void dispose() {
_cameraController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Native Camera Example'),
),
body: Center(
child: NativeCameraPreview(controller: _cameraController),
),
floatingActionButton: FloatingActionButton(
onPressed: () async {
final imagePath = await _cameraController.captureImage();
print('Image saved at: $imagePath');
},
child: Icon(Icons.camera_alt),
),
);
}
}
4. 捕获照片
在上面的代码中,_cameraController.captureImage()
方法用于捕获照片。捕获的照片将保存到设备的存储中,并返回文件的路径。
5. 捕获视频
如果你想捕获视频,可以使用 _cameraController.captureVideo()
方法。同样,视频文件将保存到设备的存储中,并返回文件的路径。
floatingActionButton: FloatingActionButton(
onPressed: () async {
final videoPath = await _cameraController.captureVideo();
print('Video saved at: $videoPath');
},
child: Icon(Icons.videocam),
),
6. 处理权限
在 Android 和 iOS 上,你需要确保应用有权限访问相机。你可以使用 permission_handler
插件来请求和检查权限。
import 'package:permission_handler/permission_handler.dart';
Future<void> _checkPermissions() async {
var status = await Permission.camera.status;
if (!status.isGranted) {
await Permission.camera.request();
}
}
在 initState
中调用 _checkPermissions()
以确保应用有权限访问相机。
7. 处理相机方向
你还可以通过 _cameraController.setFlashMode()
和 _cameraController.setFocusMode()
等方法调整相机的设置。
8. 处理相机生命周期
确保在 dispose
方法中释放相机资源,以避免内存泄漏。
@override
void dispose() {
_cameraController.dispose();
super.dispose();
}
9. 处理异常
在实际应用中,你应该捕获并处理可能出现的异常,例如相机初始化失败或权限被拒绝。
try {
await _cameraController.initialize();
} catch (e) {
print('Failed to initialize camera: $e');
}