Commit a6505868 by tanghuan

权限设置引导,以及一些优化

1 parent 67ce5110
......@@ -2,6 +2,7 @@ import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:app_settings/app_settings.dart';
import 'package:appframe/config/constant.dart';
import 'package:appframe/config/locator.dart';
import 'package:appframe/config/routes.dart';
......@@ -12,12 +13,14 @@ import 'package:appframe/services/local_server_service.dart';
import 'package:appframe/services/player_service.dart';
import 'package:appframe/services/recorder_service.dart';
import 'package:appframe/utils/zip_util.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:dio/dio.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:fluwx/fluwx.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:uuid/uuid.dart';
import 'package:webview_flutter/webview_flutter.dart';
......@@ -59,7 +62,9 @@ class WebState extends Equatable {
final bool chooseVideoCmdFlag;
final String chooseVideoCmdMessage;
const WebState({
final String h5Version;
WebState({
this.selectedIndex = 0,
this.loaded = false,
this.isUpgrading = false,
......@@ -82,7 +87,8 @@ class WebState extends Equatable {
this.chooseImageCmdMessage = '',
this.chooseVideoCmdFlag = false,
this.chooseVideoCmdMessage = '',
});
String? h5Version,
}) : this.h5Version = h5Version ?? getIt.get<SharedPreferences>().getString("h5_version") ?? Constant.h5Version;
WebState copyWith({
int? selectedIndex,
......@@ -108,6 +114,7 @@ class WebState extends Equatable {
String? chooseImageCmdMessage,
bool? chooseVideoCmdFlag,
String? chooseVideoCmdMessage,
String? h5Version,
}) {
return WebState(
selectedIndex: selectedIndex ?? this.selectedIndex,
......@@ -132,6 +139,7 @@ class WebState extends Equatable {
chooseImageCmdMessage: chooseImageCmdMessage ?? this.chooseImageCmdMessage,
chooseVideoCmdFlag: chooseVideoCmdFlag ?? this.chooseVideoCmdFlag,
chooseVideoCmdMessage: chooseVideoCmdMessage ?? this.chooseVideoCmdMessage,
h5Version: h5Version ?? this.h5Version,
);
}
......@@ -159,6 +167,7 @@ class WebState extends Equatable {
chooseImageCmdMessage,
chooseVideoCmdFlag,
chooseVideoCmdMessage,
h5Version,
];
}
......@@ -475,9 +484,9 @@ class WebCubit extends Cubit<WebState> {
Future<void> clearStorage() async {
// 1 清理非 h5_version 的缓存
var sharedPreferences = getIt.get<SharedPreferences>();
sharedPreferences.getKeys().forEach((key) {
sharedPreferences.getKeys().forEach((key) async {
if (!key.startsWith('h5_version')) {
sharedPreferences.remove(key);
await sharedPreferences.remove(key);
}
});
......@@ -619,16 +628,29 @@ class WebCubit extends Cubit<WebState> {
}
void _chooseImageFromAlbum(BuildContext context, int count, String unique, String cmd) async {
final List<AssetEntity>? result = await AssetPicker.pickAssets(
context,
pickerConfig: AssetPickerConfig(
maxAssets: count,
requestType: RequestType.image,
gridThumbnailSize: const ThumbnailSize.square(80),
previewThumbnailSize: const ThumbnailSize.square(150),
dragToSelect: false,
),
);
final List<AssetEntity>? result;
try {
result = await AssetPicker.pickAssets(
context,
pickerConfig: AssetPickerConfig(
maxAssets: count,
requestType: RequestType.image,
gridThumbnailSize: const ThumbnailSize.square(120),
previewThumbnailSize: const ThumbnailSize.square(150),
dragToSelect: false,
),
);
} catch (e) {
var resp = {'unique': unique, 'cmd': cmd, 'data': null, 'errMsg': 'no auth'};
_sendResponse(resp);
// 权限异常之后,检查是否已被永久拒绝,此时需要对用户进行引导
if (await _checkGalleryPermanentlyDenied()) {
_permissionLead(context, '相册权限');
}
return;
}
if (result == null || result.isEmpty) {
var resp = {'unique': unique, 'cmd': cmd, 'data': null, 'errMsg': 'cancel'};
......@@ -653,7 +675,19 @@ class WebCubit extends Cubit<WebState> {
}
void _chooseImageFromCamera(BuildContext context, String unique, String cmd) async {
AssetEntity? asset = await CameraPicker.pickFromCamera(context, pickerConfig: const CameraPickerConfig());
AssetEntity? asset;
try {
asset = await CameraPicker.pickFromCamera(context, pickerConfig: const CameraPickerConfig());
} catch (e) {
var resp = {'unique': unique, 'cmd': cmd, 'data': null, 'errMsg': 'no auth'};
_sendResponse(resp);
if (await _checkCameraPermanentlyDenied()) {
_permissionLead(context, '相机权限');
}
return;
}
if (asset == null) {
var resp = {'unique': unique, 'cmd': cmd, 'data': null, 'errMsg': 'cancel'};
......@@ -693,6 +727,64 @@ class WebCubit extends Cubit<WebState> {
};
}
///
/// 引导打开权限设置
///
Future<void> _permissionLead(BuildContext context, String permission) async {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('权限设置'),
content: Text('$permission已被拒绝,请到设置中手动开启权限'),
actions: <Widget>[
TextButton(
child: Text('取消'),
onPressed: () {
Navigator.of(context).pop();
},
),
TextButton(
child: Text('去设置'),
onPressed: () {
Navigator.of(context).pop();
AppSettings.openAppSettings(asAnotherTask: true); // 引导用户到应用设置页面
},
),
],
);
},
);
}
///
/// 检测相册权限是否被永久拒绝
///
Future<bool> _checkGalleryPermanentlyDenied() async {
PermissionStatus status;
if (Platform.isAndroid) {
final androidInfo = await DeviceInfoPlugin().androidInfo;
if (androidInfo.version.sdkInt <= 32) {
status = await Permission.storage.status;
} else {
status = await Permission.photos.status;
}
} else if (Platform.isIOS) {
status = await Permission.photos.status;
} else {
return false;
}
return PermissionStatus.permanentlyDenied == status;
}
///
/// 检测摄像头权限是否被永久拒绝
///
Future<bool> _checkCameraPermanentlyDenied() async {
PermissionStatus status = await Permission.camera.status;
return PermissionStatus.permanentlyDenied == status;
}
void setChooseVideoCmdFlag(bool chooseVideoCmdFlag, String chooseVideoCmdMessage) {
emit(state.copyWith(chooseVideoCmdFlag: chooseVideoCmdFlag, chooseVideoCmdMessage: chooseVideoCmdMessage));
}
......@@ -739,14 +831,28 @@ class WebCubit extends Cubit<WebState> {
}
void _chooseVideoFromAlbum(BuildContext context, int count, String unique, String cmd) async {
final List<AssetEntity>? result = await AssetPicker.pickAssets(
context,
pickerConfig: AssetPickerConfig(
maxAssets: count,
requestType: RequestType.video,
dragToSelect: false,
),
);
List<AssetEntity>? result;
try {
result = await AssetPicker.pickAssets(
context,
pickerConfig: AssetPickerConfig(
maxAssets: count,
requestType: RequestType.video,
dragToSelect: false,
),
);
} catch (e) {
var resp = {'unique': unique, 'cmd': cmd, 'data': null, 'errMsg': 'no auth'};
_sendResponse(resp);
// 权限异常之后,检查是否已被永久拒绝,此时需要对用户进行引导
if (await _checkGalleryPermanentlyDenied()) {
_permissionLead(context, '相册权限');
}
return;
}
if (result == null || result.isEmpty) {
var resp = {'unique': unique, 'cmd': cmd, 'data': null, 'errMsg': 'cancel'};
......@@ -771,15 +877,27 @@ class WebCubit extends Cubit<WebState> {
}
void _chooseVideoFromCamera(BuildContext context, int maxDuration, String unique, String cmd) async {
AssetEntity? asset = await CameraPicker.pickFromCamera(
context,
pickerConfig: CameraPickerConfig(
enableRecording: true,
onlyEnableRecording: true,
// enableTapRecording: true,
maximumRecordingDuration: Duration(seconds: maxDuration),
),
);
AssetEntity? asset;
try {
asset = await CameraPicker.pickFromCamera(
context,
pickerConfig: CameraPickerConfig(
enableRecording: true,
onlyEnableRecording: true,
// enableTapRecording: true,
maximumRecordingDuration: Duration(seconds: maxDuration),
),
);
} catch (e) {
var resp = {'unique': unique, 'cmd': cmd, 'data': null, 'errMsg': 'no auth'};
_sendResponse(resp);
if (await _checkCameraPermanentlyDenied()) {
_permissionLead(context, '相机权限');
}
return;
}
if (asset == null) {
var resp = {'unique': unique, 'cmd': cmd, 'data': null, 'errMsg': 'cancel'};
......
......@@ -57,6 +57,13 @@ class RemoveStorageHandler extends MessageHandler {
class ClearStorageHandler extends MessageHandler {
@override
Future<dynamic> handleMessage(dynamic params) async {
return await getIt.get<SharedPreferences>().clear();
var sharedPreferences = getIt.get<SharedPreferences>();
sharedPreferences.getKeys().forEach((key) async {
if (!key.startsWith('h5_version')) {
await sharedPreferences.remove(key);
}
});
return true;
}
}
......@@ -151,12 +151,13 @@ class WebPage extends StatelessWidget {
child: Column(
children: [
Text(
'Version ${Constant.appVersion}',
'Version ${Constant.appVersion}-${state.h5Version}',
style: TextStyle(
color: Colors.grey,
fontSize: 12,
),
),
SizedBox(height: 8),
Text(
'Copyright © 中山班小二科技有限公司',
),
......
Styling with Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!