flutter学习之权限申请相关,选择本地图片,视频,拍照
在flutter中权限申请和拍照视频都是依赖一些库实现。 相关的库如下:
# 获取设备信息
device_info_plus: ^2.1.0
#动态权限申请
permission_handler: ^8.1.4+2
#选择相册
image_picker: ^0.8.3+2
# 视频播放
video_player: ^2.1.12
chewie: ^1.2.2
可以自己在https://pub.flutter-io.cn/上面搜索该库,查看使用方法
一、获取设备信息
device_info_plus是一个获取设备信息的库,支持Android iOS MacOS Web Linux Windows这几个平台,是Flutter 团队开发的。
import 'package:device_info_plus/device_info_plus.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_view_demo/res/ShowToast.dart';
import 'package:fluttertoast/fluttertoast.dart';
class TesttwentYThree extends StatefulWidget {
const TesttwentYThree({Key? key}) : super(key: key);
@override
_TesttwentYThreeState createState() => _TesttwentYThreeState();
}
class _TesttwentYThreeState extends State<TesttwentYThree> {
late AndroidDeviceInfo androidInfo;
@override
void initState() {
super.initState();
_getDevice();
}
_getDevice() async{
DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
androidInfo = await deviceInfo.androidInfo;
print('Running on ${androidInfo.model}');
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("获取设备信息"),),
body: ListView(
children: [
ListTile(
title: Text("version"),
onTap: (){
showToast("${androidInfo.version}");
},
),
ListTile(
title: Text("board"),
onTap: (){
showToast("${androidInfo.board}");
},
),
ListTile(
title: Text("bootloader"),
onTap: (){
showToast("${androidInfo.bootloader}");
},
),
ListTile(
title: Text("brand"),
onTap: (){
showToast("${androidInfo.brand}");
},
),
ListTile(
title: Text("device"),
onTap: (){
showToast("${androidInfo.device}");
},
),
ListTile(
title: Text("fingerprint"),
onTap: (){
showToast("${androidInfo.fingerprint}");
},
),
ListTile(
title: Text("display"),
onTap: (){
showToast("${androidInfo.display}");
},
),
ListTile(
title: Text("hardware"),
onTap: (){
showToast("${androidInfo.hardware}");
},
),
ListTile(
title: Text("host"),
onTap: (){
showToast("${androidInfo.host}");
},
),
ListTile(
title: Text("id"),
onTap: (){
showToast("${androidInfo.id}");
},
),ListTile(
title: Text("manufacturer"),
onTap: (){
showToast("${androidInfo.manufacturer}");
},
),ListTile(
title: Text("model"),
onTap: (){
showToast("${androidInfo.model}");
},
),ListTile(
title: Text("product"),
onTap: (){
showToast("${androidInfo.product}");
},
),ListTile(
title: Text("tags"),
onTap: (){
showToast("${androidInfo.tags}");
},
),ListTile(
title: Text("type"),
onTap: (){
showToast("${androidInfo.type}");
},
),ListTile(
title: Text("isPhysicalDevice"),
onTap: (){
showToast("${androidInfo.isPhysicalDevice}");
},
),ListTile(
title: Text("androidId"),
onTap: (){
showToast("${androidInfo.androidId}");
},
),
],
),
);
}
}
二、动态权限申请
三方库地址:https://pub.flutter-io.cn/packages/permission_handler
用之前Android和IOS都需要在对应工程下做相关配置: Android: 1.将以下内容添加到您的“gradle.properties”文件中:
android.useAndroidX=true
android.enableJetifier=true
2.确保compileSdkVersion将“android/app/build.gradle”文件中的 设置为 30: 在app下build.gradle文件里
android {
compileSdkVersion 30
...
}
IOS:请查看官方文档
批量申请权限:
void requestAllPermission() async{
if (await Permission.contacts.request().isGranted) {
}
Map<Permission, PermissionStatus> statuses = await [
Permission.location,
Permission.storage,
Permission.camera,
].request();
print(statuses[Permission.location]);
}
运行是单个权限申请
Future<bool> requestCalendarPermission() async {
var status = await Permission.phone.status;
if (status == PermissionStatus.granted) {
return true;
} else {
status = await Permission.phone.request();
if (status == PermissionStatus.granted) {
return true;
} else {
return false;
}
}
}
}
整体代码查看:
import 'package:flutter_view_demo/res/ShowToast.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class TesttwentYFour extends StatefulWidget {
const TesttwentYFour({Key? key}) : super(key: key);
@override
_TesttwentYFourState createState() => _TesttwentYFourState();
}
class _TesttwentYFourState extends State<TesttwentYFour> {
@override
void initState() {
super.initState();
requestAllPermission();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("权限申请"),
),
body: ListView(
children: [
ListTile(
title: Text("动态申请定位权限"),
onTap: (){
requestPermission(0);
},
),
ListTile(
title: Text("动态申请相机权限"),
onTap: (){
requestPermission(1);
},
),
ListTile(
title: Text("动态申请存储权限"),
onTap: (){
requestPermission(2);
},
),
ListTile(
title: Text("动态申请设备信息权限"),
onTap: (){
requestPermission(3);
},
),
],
),
);
}
void requestAllPermission() async{
if (await Permission.contacts.request().isGranted) {
}
Map<Permission, PermissionStatus> statuses = await [
Permission.location,
Permission.storage,
Permission.camera,
].request();
print(statuses[Permission.location]);
}
void requestPermission(int type) async {
late bool hasLocationPermission;
if(type ==0){
hasLocationPermission = await requestLocationPermission();
}else if(type ==1){
hasLocationPermission = await requestCameraPermission();
}else if(type ==2){
hasLocationPermission = await requestWritePermission();
}else if(type ==3){
hasLocationPermission = await requestCalendarPermission();
}
if (hasLocationPermission) {
showToast("权限申请通过");
} else {
showToast("权限申请不通过");
}
}
Future<bool> requestLocationPermission() async {
var status = await Permission.location.status;
if (status == PermissionStatus.granted) {
return true;
} else {
status = await Permission.location.request();
if (status == PermissionStatus.granted) {
return true;
} else {
return false;
}
}
}
Future<bool> requestCameraPermission() async {
var status = await Permission.camera.status;
if (status == PermissionStatus.granted) {
return true;
} else {
status = await Permission.camera.request();
if (status == PermissionStatus.granted) {
return true;
} else {
return false;
}
}
}
Future<bool> requestWritePermission() async {
var status = await Permission.storage.status;
if (status == PermissionStatus.granted) {
return true;
} else {
status = await Permission.storage.request();
if (status == PermissionStatus.granted) {
return true;
} else {
return false;
}
}
}
Future<bool> requestCalendarPermission() async {
var status = await Permission.phone.status;
if (status == PermissionStatus.granted) {
return true;
} else {
status = await Permission.phone.request();
if (status == PermissionStatus.granted) {
return true;
} else {
return false;
}
}
}
}
三、拍照和相册
Image Picker plugin for Flutter是Flutter官方提供的一个图片选择库,里面自带动态权限申请,不需要自己再去申请权限了。主要适用于Android和IOS端, 相关方法:
import 'package:image_picker/image_picker.dart';
...
final ImagePicker _picker = ImagePicker();
final XFile? image = await _picker.pickImage(source: ImageSource.gallery);
final XFile? photo = await _picker.pickImage(source: ImageSource.camera);
final XFile? image = await _picker.pickVideo(source: ImageSource.gallery);
final XFile? photo = await _picker.pickVideo(source: ImageSource.camera);
final List<XFile>? images = await _picker.pickMultiImage();
...
具体实现:
import 'dart:io';
import 'package:image_picker/image_picker.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class TesttwentYFive extends StatefulWidget {
const TesttwentYFive({Key? key}) : super(key: key);
@override
_TesttwentYFiveState createState() => _TesttwentYFiveState();
}
class _TesttwentYFiveState extends State<TesttwentYFive> {
final ImagePicker _picker = ImagePicker();
XFile? _photo;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("相册,拍照"),),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
this._photo == null?Text("请选择图片"):Image.file(File(_photo!.path)),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(onPressed: (){
_takePhoto();
}, child: Text("拍照")),
SizedBox(width: 10,),
ElevatedButton(onPressed: (){
_galleryPhoto();
}, child: Text("相册")),
SizedBox(width: 10,),
ElevatedButton(onPressed: (){
_choicePhoto();
}, child: Text("相册多选")),
],
)
],
),
),
);
}
_takePhoto() async{
XFile? photo = await _picker.pickImage(source: ImageSource.camera,maxWidth: 400,maxHeight: 400);
if(photo != null){
setState(() {
this._photo = photo;
});
}
}
_galleryPhoto() async{
XFile? photo = await _picker.pickImage(source: ImageSource.gallery,maxWidth: 400,maxHeight: 400);
if(photo != null){
setState(() {
this._photo = photo;
});
}
}
_choicePhoto() async{
final List<XFile>? images = await _picker.pickMultiImage();
}
}
四、视频播放
video_player是flutter官方提供的一个视频播放库,支持ANDROID IOS WEB,但是只有播放功能,所以的需求功能都需要扩展,所以需要搭配其他的库一起使用。 chewie是一个video_player的播放扩展库。三方库地址: video_player:https://pub.flutter-io.cn/packages/video_player/install chewie:https://pub.flutter-io.cn/packages/chewie
1.加载网络视频
class NetVideoPlayer extends StatefulWidget {
const NetVideoPlayer({Key? key}) : super(key: key);
@override
_NetVideoPlayerState createState() => _NetVideoPlayerState();
}
class _NetVideoPlayerState extends State<NetVideoPlayer> {
late VideoPlayerController videoPlayerController;
late ChewieController chewieController;
@override
initState() {
super.initState();
_initVideo();
}
_initVideo() async {
videoPlayerController = VideoPlayerController.network(
'https://vfx.mtime.cn/Video/2019/02/04/mp4/190204084208765161.mp4');
chewieController = ChewieController(
videoPlayerController: videoPlayerController,
autoPlay: true,
looping: true,
);
}
@override
void dispose() {
videoPlayerController.dispose();
chewieController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("网络视频播放"),
),
body: Center(
child: Chewie(
controller: chewieController,
),
),
);
}
}
2.加载本地视频
获取本地视频。获取成功跳转播放视频页
final ImagePicker _picker = ImagePicker();
_getVideo() async{
final XFile? image = await _picker.pickVideo(source: ImageSource.gallery);
if(image != null){
String videoPath = image.path;
Navigator.pushNamed(context, "/LocationVideoPlay",arguments: {
"videoPath":videoPath
});
}
}
class LocationVideoPlay extends StatefulWidget {
var arguments;
LocationVideoPlay({Key? key,this.arguments}) : super(key: key);
@override
_LocationVideoPlayState createState() => _LocationVideoPlayState(this.arguments);
}
class _LocationVideoPlayState extends State<LocationVideoPlay> {
var arguments;
_LocationVideoPlayState(this.arguments);
late VideoPlayerController videoPlayerController;
late ChewieController chewieController;
@override
initState() {
super.initState();
_initVideo();
}
_initVideo() async {
videoPlayerController = VideoPlayerController.file(File(arguments["videoPath"]));
chewieController = ChewieController(
videoPlayerController: videoPlayerController,
autoPlay: true,
looping: true,
);
}
@override
void dispose() {
videoPlayerController.dispose();
chewieController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("本地视频播放"),),
body: Center(
child: Chewie(
controller: chewieController,
),
),
);
}
}
总结
|