face_capture 0.0.1
face_capture: ^0.0.1 copied to clipboard
A neww Flutter plugin project face_capture.
example/lib/main.dart
// ignore_for_file: depend_on_referenced_packages
import 'package:face_capture_example/splash_screen.dart';
import 'package:face_capture_example/web_view_container.dart';
import 'package:flutter/material.dart';
import 'package:face_capture/face_capture.dart';
import 'package:flutter/services.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:http/http.dart';
import 'fc_about.dart';
import 'fc_settings.dart';
import 'globals.dart';
import 'globals.dart' as globals;
import 'init.dart';
import 'liveness_json.dart';
import 'capture_page.dart';
void main() async {
if (Globals.faceCaptureLibrary != null) {
Globals.faceCaptureLibrary!.dispose();
debugPrint("MainPage DESTROY.....");
} else {
Globals.faceCaptureLibrary = null;
Globals.faceCaptureWorkflow = null;
Globals.profiles = [];
Globals.userName = "";
Globals.cameraPosition = "";
Globals.screenOrientation = Orientation.portrait;
Globals.packageType = "";
Globals.livenessUrl = "";
Globals.workflow = "";
Globals.captureTimeout = "";
Globals.profile = "";
Globals.livenessServerVersion = "";
Globals.faceCaptureVersion = "";
Globals.livenessServerStatus = false;
}
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
@override
_MyState createState() => _MyState();
}
class _MyState extends State<MyApp> with WidgetsBindingObserver {
final Future _initFuture = Init.initialize();
@override
void initState() {
super.initState();
// Add the observer.
WidgetsBinding.instance!.addObserver(this);
checkPermission();
}
@override
void dispose() {
// Remove the observer
WidgetsBinding.instance!.removeObserver(this);
super.dispose();
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
super.didChangeAppLifecycleState(state);
// These are the callbacks
switch (state) {
case AppLifecycleState.resumed:
// widget is resumed
debugPrint("MainPage On-Resumed.....");
break;
case AppLifecycleState.inactive:
// widget is inactive
debugPrint("MainPage On-Inactive.....");
break;
case AppLifecycleState.paused:
// widget is paused
debugPrint("MainPage On-Paused.....");
break;
case AppLifecycleState.detached:
// widget is detached
Globals.faceCaptureLibrary?.dispose();
debugPrint("MainPage On-Detached.....");
break;
}
}
checkPermission() async {
if (await Permission.camera.request().isGranted) {
// Either the permission was already granted before or the user just granted it.
}
}
@override
Widget build(BuildContext context) {
//Set the fit size (fill in the screen size of the device in the design) The design is based on the size of the Pixel4a (1080x2340)
return ScreenUtilInit(
designSize: const Size(1080, 2340),
builder: () => MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Flutter_ScreenUtil',
theme: ThemeData(
primarySwatch: Colors.blue,
textTheme: TextTheme(button: TextStyle(fontSize: 45.sp)),
),
builder: (context, widget) {
return MediaQuery(
//Setting font does not change with system font size
data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0),
child: widget!,
);
},
// home: ActionButton(),
home: FutureBuilder(
future: _initFuture,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasData) {
globals.InitializeResult? responseData =
globals.InitializeResult(0, "msg");
responseData = snapshot.data as globals.InitializeResult?;
var err = responseData?.err;
var msg = responseData?.msg;
debugPrint("Initialization error = $err, $msg");
}
return const ActionButton();
} else {
return const SplashScreen();
}
},
),
),
);
}
}
class ActionButton extends StatefulWidget {
const ActionButton({Key? key}) : super(key: key);
@override
State<ActionButton> createState() => _ActionButtonState();
}
class CameraList {
String number;
int index;
CameraList({required this.number, required this.index});
}
class _ActionButtonState extends State<ActionButton> {
String _livenessResult = "";
// Default Radio Button Selected Item.
String radioItemHolder = "";
// Group Value for Radio Button.
int id = 0;
List<CameraList> camList = [];
Future<void> makePostRequest() async {
PackageType pkgType = PackageType.highUsability;
if (Globals.packageType == "High Usability") {
pkgType = PackageType.highUsability;
} else if (Globals.packageType == "Balanced") {
pkgType = PackageType.balanced;
} else {
pkgType = PackageType.highSecurity;
}
debugPrint('packageType = $pkgType');
String serverPackageJson = Globals.faceCaptureLibrary!
.getServerPackage(Globals.faceCaptureWorkflow!, pkgType);
String urlPrefix = Globals.livenessUrl;
final url = Uri.parse('$urlPrefix/checkLiveness');
final headers = {"Content-type": "application/json"};
final response = await post(url, headers: headers, body: serverPackageJson);
debugPrint('Status code: ${response.statusCode}');
debugPrint('Body: ${response.body}');
final welcome = welcomeFromJson(response.body);
String decision = welcome.video.livenessResult.decision;
setState(() {
_livenessResult = decision;
_showMyDialog();
});
}
void _awaitReturnValueFromCapturePage(BuildContext context) async {
// start the SecondScreen and wait for it to finish with a result
final result = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const CapturePage(),
));
debugPrint("......Result=$result");
if (result == 1) {
//Get the liveness result.
makePostRequest();
}
}
Widget _portraitMode() {
captureButtonPressed() {
//Get cameras.
int len = Globals.cameras.length;
if(len == 1) {
Future<int> result = _startFaceCapture(0);
_awaitReturnValueFromCapturePage(context);
return;
}
id = 0;
camList.clear();
for (int i = 0; i < len; i++) {
camList.add(
CameraList(
number: Globals.cameras[i].getName(),
index: i,
),
);
}
showDialog<void>(
context: context,
barrierDismissible: false, // user must tap button!
builder: (BuildContext context) {
return AlertDialog(
title: Center(
child: Text('Select camera',
style: TextStyle(fontSize: 75.0.sp))),
content: StatefulBuilder(
builder: (BuildContext context,
StateSetter setState) =>
SizedBox(
height: 460.h,
child: Column(
children: <Widget>[
SizedBox(
height: 460.h,
child: Column(
children: camList
.map((data) => RadioListTile(
title: Text(data.number),
groupValue: id,
value: data.index,
onChanged: (val) {
setState(() {
radioItemHolder =
data.number;
id = data.index;
debugPrint(
"id=$id name=$radioItemHolder");
});
},
))
.toList(),
),
),
],
),
),
),
actions: <Widget>[
Center(
child: ElevatedButton(
child: const Text('OK'),
style: TextButton.styleFrom(
padding: EdgeInsets.all(12.0.w),
primary: Colors.white,
textStyle: TextStyle(fontSize: 40.0.sp),
backgroundColor: Colors.blue,
),
onPressed: () {
Navigator.pop(context);
Future<int> result = _startFaceCapture(id);
_awaitReturnValueFromCapturePage(context);
},
),
),
],
);
},
);
}
return SafeArea(
child: Scaffold(
backgroundColor: Colors.white,
body: Center(
child: Column(
children: <Widget>[
SizedBox(
height: 100.h,
),
Image.asset(
'assets/aware_social.png',
height: 450.h,
width: 450.w,
),
SizedBox(
height: 100.h,
),
Text(
'Face Capture SDK',
style: TextStyle(fontSize: 75.0.sp, height: 1.0.h),
),
SizedBox(
//Use of SizedBox
height: 120.h,
),
Text(
'Sample Application',
style: TextStyle(fontSize: 50.0.sp, height: 1.0.h),
),
SizedBox(
height: 150.h,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ElevatedButton(
child: const Text('Capture'),
onPressed: Globals.livenessServerStatus ? ()=> captureButtonPressed() : null,
),
],
),
SizedBox(
height: 150.h,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text('Username:',
style: TextStyle(fontSize: 60.0.sp, height: null)),
Text(Globals.userName,
style: TextStyle(fontSize: 60.0.sp, height: null)),
],
),
SizedBox(
height: 50.h,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text('Workflow:',
style: TextStyle(fontSize: 60.0.sp, height: null)),
Text(Globals.workflow,
style: TextStyle(fontSize: 60.0.sp, height: null)),
],
),
SizedBox(
height: 50.h,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text('Server Status:',
style: TextStyle(fontSize: 60.0.sp, height: null)),
if (Globals.livenessServerStatus)
Image.asset(
'assets/check_icon.png',
height: 80.h,
width: 80.w,
)
else
Image.asset(
'assets/delete_icon.png',
height: 80.h,
width: 80.w,
),
],
),
],
),
)),
);
}
Widget _landscapeMode() {
double sb1h = 150;
double sb2h = 100;
double sb3h = 120;
double sb4h = 120;
double sb5h = 120;
double sb6h = 50;
double sb7h = 50;
double sb8h = 460;
double img1h = 375;
double img1w = 375;
double fs1 = 90;
double fs2 = 65;
double fs3 = 75;
// Adjust widgets based on if we are a tablet or phone.
if (MediaQuery.of(context).size.height > 600) {
//isLargeScreen = true;
sb1h = 150;
sb2h = 100;
sb3h = 120;
sb4h = 120;
sb5h = 120;
sb6h = 50;
sb7h = 50;
sb8h = 460;
img1h = 375;
img1w = 375;
fs1 = 90;
fs2 = 65;
fs3 = 75;
} else {
//isLargeScreen = false;
sb1h = 10;
sb2h = 60;
sb3h = 75;
sb4h = 20;
sb5h = 20;
sb6h = 20;
sb7h = 20;
sb8h = 400;
img1h = 175;
img1w = 175;
fs1 = 85;
fs2 = 60;
fs3 = 70;
}
captureButtonPressed() {
//Get cameras.
int len = Globals.cameras.length;
if(len == 1) {
Future<int> result = _startFaceCapture(0);
_awaitReturnValueFromCapturePage(context);
return;
}
id = 0;
camList.clear();
for (int i = 0; i < len; i++) {
camList.add(
CameraList(
number: Globals.cameras[i].getName(),
index: i,
),
);
}
showDialog<void>(
context: context,
barrierDismissible: false, // user must tap button!
builder: (BuildContext context) {
return AlertDialog(
title: Center(
child: Text('Select camera',
style: TextStyle(fontSize: 75.0.sp))),
content: StatefulBuilder(
builder: (BuildContext context,
StateSetter setState) =>
SizedBox(
height: sb8h.h,
child: Column(
children: <Widget>[
SizedBox(
height: sb8h.h,
child: Column(
children: camList
.map((data) => RadioListTile(
title: Text(data.number),
groupValue: id,
value: data.index,
onChanged: (val) {
setState(() {
radioItemHolder =
data.number;
id = data.index;
debugPrint(
"id=$id name=$radioItemHolder");
});
},
))
.toList(),
),
),
],
),
),
),
actions: <Widget>[
Center(
child: ElevatedButton(
child: const Text('OK'),
style: TextButton.styleFrom(
padding: EdgeInsets.all(12.0.w),
primary: Colors.white,
textStyle: TextStyle(fontSize: 40.0.sp),
backgroundColor: Colors.blue,
),
onPressed: () {
Navigator.pop(context);
Future<int> result = _startFaceCapture(id);
_awaitReturnValueFromCapturePage(context);
},
),
),
],
);
},
);
}
return SafeArea(
child: Scaffold(
backgroundColor: Colors.white,
body: Center(
child: Column(
children: <Widget>[
SizedBox(
height: sb1h.h,
),
Image.asset(
'assets/aware_social.png',
height: img1h.h,
width: img1w.w,
),
SizedBox(
height: sb2h.h,
),
Text(
'Face Capture SDK',
style: TextStyle(fontSize: fs1.sp, height: 1.0.h),
),
SizedBox(
//Use of SizedBox
height: sb3h.h,
),
Text(
'Sample Application',
style: TextStyle(fontSize: fs2.sp, height: 1.0.h),
),
SizedBox(
height: sb4h.h,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ElevatedButton(
child: Text(
'Capture',
style: TextStyle(fontSize: fs2.sp),
),
onPressed: Globals.livenessServerStatus ? ()=> captureButtonPressed() : null,
),
],
),
SizedBox(
height: sb5h.h,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text('Username:',
style: TextStyle(fontSize: fs3.sp, height: null)),
Text(Globals.userName,
style: TextStyle(fontSize: fs3.sp, height: null)),
],
),
SizedBox(
height: sb6h.h,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text('Workflow:',
style: TextStyle(fontSize: fs3.sp, height: null)),
Text(Globals.workflow,
style: TextStyle(fontSize: fs3.sp, height: null)),
],
),
SizedBox(
height: sb7h.h,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text('Server Status:',
style: TextStyle(fontSize: fs3.sp, height: null)),
if (Globals.livenessServerStatus)
Image.asset(
'assets/check_icon.png',
height: 80.h,
width: 80.w,
)
else
Image.asset(
'assets/delete_icon.png',
height: 80.h,
width: 80.w,
),
],
),
],
),
)),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
title: const Text('Face Capture Demo'),
actions: [
PopupMenuButton(
itemBuilder: (BuildContext bc) => [
const PopupMenuItem(child: Text("Settings"), value: "/settings"),
const PopupMenuItem(child: Text("Privacy"), value: "/privacy"),
const PopupMenuItem(child: Text("Licenses"), value: "/licenses"),
const PopupMenuItem(child: Text("About"), value: "/about"),
],
onSelected: (route) {
debugPrint(route.toString());
if (route == "/settings") {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const Settings()),
);
}
if (route == "/privacy") {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const WebViewContainer(
'https://www.aware.com/privacy/mobileapps')));
}
if (route == "/licenses") {
showLicensePage(context: context);
}
if (route == "/about") {
showDialog(
context: context,
builder: (BuildContext context) => const About());
}
},
),
],
),
body: OrientationBuilder(
builder: (context, orientation) {
if (orientation == Orientation.portrait) {
Globals.screenOrientation = Orientation.portrait;
return _portraitMode();
} else {
// Adjust widgets based on if we are a tablet or phone.
//Only do landscape on large devices.
if (MediaQuery.of(context).size.height > 600) {
//isLargeScreen = true;
Globals.screenOrientation = Orientation.landscape;
return _landscapeMode();
} else {
Globals.screenOrientation = Orientation.portrait;
SystemChrome.setPreferredOrientations(
[DeviceOrientation.portraitUp]
);
return _portraitMode();
}
}
},
),
);
}
Future<int> _startFaceCapture(int cameraId) async {
try {
int len = Globals.cameras.length;
for (int i = 0; i < len; i++) {
String name = Globals.cameras[i].getName();
debugPrint("......_startFaceCapture-camera name$i=$name");
}
Globals.faceCaptureLibrary!.startCaptureSession(
Globals.faceCaptureWorkflow!, Globals.cameras[cameraId]);
if (Globals.screenOrientation == Orientation.portrait) {
Globals.captureRegion = Globals.faceCaptureLibrary!.captureSessionGetCaptureRegion();
} else {
Globals.captureRegion = Globals.faceCaptureLibrary!.captureSessionGetCaptureRegion();
}
debugPrint("Capture Region = " + Globals.captureRegion.toString());
} on FaceCaptureException catch (e) {
debugPrint("Start Capture error-errorCode=${e.errorCode}");
}
return 0;
}
Future<void> _showMyDialog() async {
return showDialog<void>(
context: context,
barrierDismissible: false, // user must tap button!
builder: (BuildContext context) {
return AlertDialog(
title: Center(
child: Text('CAPTURE', style: TextStyle(fontSize: 75.0.sp))),
content: SingleChildScrollView(
child: Column(
children: <Widget>[
Text("Video - " + _livenessResult,
style: TextStyle(fontSize: 68.0.sp)),
SizedBox(
height: 20.h,
),
Image.memory(imgBuf, scale: 3),
],
),
),
actions: <Widget>[
Center(
child: ElevatedButton(
child: const Text('OK'),
style: TextButton.styleFrom(
padding: EdgeInsets.all(12.0.w),
primary: Colors.white,
textStyle: TextStyle(fontSize: 40.0.sp),
backgroundColor: Colors.blue,
),
onPressed: () {
Navigator.pop(context);
},
),
),
],
);
},
);
}
}