<|start_filename|>android/src/main/java/com/hs/face/FaceMethodCall.java<|end_filename|>
package com.hs.face;

import android.app.Activity;
import android.util.Log;

import com.arcsoft.face.ActiveFileInfo;
import com.arcsoft.face.ErrorInfo;
import com.arcsoft.face.FaceEngine;
import com.arcsoft.face.VersionInfo;
import com.arcsoft.face.enums.DetectFaceOrientPriority;
import com.hs.face.util.ConfigUtil;

import io.flutter.plugin.common.MethodChannel.Result;

public class FaceMethodCall {

    private static final String TAG = "FaceMethodCall";
    private Activity activity;

    public FaceMethodCall(Activity activity) {
        this.activity = activity;
    }

    /**
     * 执行注册sdk
     * @param appId
     * @param sdkKey
     * @param result
     */
    public void handlerActiveOnline(String appId, String sdkKey, Result result) {
        Log.i(TAG,"context："+activity+"，appId："+appId+"，sdkKey："+sdkKey);
        int code = FaceEngine.activeOnline(activity, appId, sdkKey);
        Log.i(TAG,"engine result："+code);
        if(code == ErrorInfo.MOK || code == ErrorInfo.MERR_ASF_ALREADY_ACTIVATED){
            result.success(true);
        } else {
            Log.e(TAG,"Face SDK Register Error，ErrorCode： "+code);
            result.error(""+code,"激活失败，错误码："+code+"请根据错误码查询对应错误", null);
        }
    }

    /**
     * 获取激活文件信息
     * @return
     */
    public void handlerGetActiveFileInfo(Result result) {
        ActiveFileInfo activeFileInfo = new ActiveFileInfo();
        int code = FaceEngine.getActiveFileInfo(activity, activeFileInfo);
        if (code == ErrorInfo.MOK){
            Log.i(TAG,"获取激活文件信息："+activeFileInfo.toString());
            result.success(activeFileInfo);
        }else{
            Log.e(TAG,"GetActiveFileInfo failed, code is  : " + code);
            result.error(""+code,"获取激活文件信息失败，错误码："+code+"请根据错误码查询对应错误", null);
        }
    }

    /**
     * 获取sdk版本
     * @return
     */
    public void handlerGetSdkVersion(Result result) {
        VersionInfo versionInfo = new VersionInfo();
        int code = FaceEngine.getVersion(versionInfo);
        if (code == ErrorInfo.MOK){
            Log.i(TAG,"获取版本信息："+versionInfo.toString());
            result.success(versionInfo);
        }else{
            Log.e(TAG,"GetSdkVersion failed, code is  : " + code);
            result.error(""+code,"获取sdk版本信息，错误码："+code+"请根据错误码查询对应错误", null);
        }
    }

    /// 设置视频人脸检测角度
    public void handlerSetFaceDetectOrientPriority(int faceDetectOrientPriority, Result result) {
        switch (faceDetectOrientPriority) {
            case 1:
                ConfigUtil.setFtOrient(activity, DetectFaceOrientPriority.ASF_OP_0_ONLY);
                break;
            case 2:
                ConfigUtil.setFtOrient(activity, DetectFaceOrientPriority.ASF_OP_90_ONLY);
                break;
            case 3:
                ConfigUtil.setFtOrient(activity, DetectFaceOrientPriority.ASF_OP_270_ONLY);
                break;
            case 4:
                ConfigUtil.setFtOrient(activity, DetectFaceOrientPriority.ASF_OP_180_ONLY);
                break;
            default:
                ConfigUtil.setFtOrient(activity, DetectFaceOrientPriority.ASF_OP_ALL_OUT);
                break;
        }
        result.success(faceDetectOrientPriority);
    }
}


<|start_filename|>lib/model/face_detect_info_model.dart<|end_filename|>
class FaceDetectInfoModel {
  FaceRectModel rect;
  int sex;
  int age;
  int liveness;
  int color;
  String name;

  FaceDetectInfoModel({
    this.rect,
    this.sex: -1,
    this.age: 0,
    this.liveness: -1,
    this.color: -1
  });

  factory FaceDetectInfoModel.fromJson(Map<String, dynamic> json) => FaceDetectInfoModel(
    rect: json["rect"] == null ? new FaceRectModel() : FaceRectModel.fromJson(json["rect"]),
    sex: json["sex"] == null ? -1 : json["sex"],
    age: json["age"] == null ? 0 : json["age"],
    liveness: json["liveness"] == null ? -1 : json["liveness"],
    color: json["color"] == null ? -1 : json["color"],
  );

  Map<String, dynamic> toJson() => {
    "rect": rect == null ? null : rect,
    "sex": sex == null ? null : sex,
    "age": age == null ? null : age,
    "liveness": liveness == null ? null : liveness,
    "color": color == null ? null : color
  };
}

class FaceRectModel {
  int bottom;
  int left;
  int right;
  int top;

  FaceRectModel({
    this.bottom: 0,
    this.left: 0,
    this.right: 0,
    this.top: 0
  });

  factory FaceRectModel.fromJson(Map<String, dynamic> json) => FaceRectModel(
    bottom: json["bottom"] == null ? 0 : json["bottom"],
    left: json["left"] == null ? 0 : json["left"],
    right: json["right"] == null ? 0 : json["right"],
    top: json["top"] == null ? 0 : json["top"],
  );

  Map<String, dynamic> toJson() => {
    "bottom": bottom == null ? null : bottom,
    "left": left == null ? null : left,
    "right": right == null ? null : right,
    "top": top == null ? null : top
  };
}

<|start_filename|>android/src/main/java/com/hs/face/widget/FaceRectView.java<|end_filename|>
package com.hs.face.widget;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

import androidx.annotation.Nullable;

import com.hs.face.model.DrawInfo;
import com.hs.face.util.DrawHelper;

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * 用于显示人脸信息的控件
 */
public class FaceRectView extends View {
    private static final String TAG = "FaceRectView";
    private CopyOnWriteArrayList<DrawInfo> drawInfoList = new CopyOnWriteArrayList<>();

    // 画笔，复用
    private Paint paint;

    // 默认人脸框厚度
    private static final int DEFAULT_FACE_RECT_THICKNESS = 6;

    public FaceRectView(Context context) {
        this(context, null);
    }

    public FaceRectView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        paint = new Paint();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (drawInfoList != null && drawInfoList.size() > 0) {
            for (int i = 0; i < drawInfoList.size(); i++) {
                DrawHelper.drawFaceRect(canvas, drawInfoList.get(i), DEFAULT_FACE_RECT_THICKNESS, paint);
            }
        }
    }

    public void clearFaceInfo() {
        drawInfoList.clear();
        postInvalidate();
    }

    public void addFaceInfo(DrawInfo faceInfo) {
        drawInfoList.add(faceInfo);
        postInvalidate();
    }

    public void addFaceInfo(List<DrawInfo> faceInfoList) {
        drawInfoList.addAll(faceInfoList);
        postInvalidate();
    }
}

<|start_filename|>android/src/main/java/com/hs/face/FacePlugin.java<|end_filename|>
package com.hs.face;

import android.app.Activity;
import android.os.Build;

import androidx.annotation.NonNull;

import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.PluginRegistry.Registrar;

/** FacePlugin */
public class FacePlugin implements FlutterPlugin, ActivityAware {
  private static final String TAG = "FacePlug";
  private static final String METHOD_CHANNEL = "com.hs.face/method";
  private static final String FACE_DETECT_CAMERA_VIEW_CHANNEL = "com.hs.face/face_detect_camera_view";

  private FlutterPluginBinding flutterPluginBinding;
  private FacePluginMethodCallHandler methodCallHandler;

  /// 1.12版本之前使用此方法进行插件注册
  public static void registerWith(Registrar registrar) {
    final FacePlugin instance = new FacePlugin();
    instance.pluginRegister(registrar.activity(), registrar.messenger());
    registrar.platformViewRegistry().
            registerViewFactory(FACE_DETECT_CAMERA_VIEW_CHANNEL, new FaceDetectCameraFactory(
                    registrar.activity(),
                    registrar.messenger()
            ));
  }

  /// 1.12版本开始使用此方法进行插件注册
  @Override
  public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) {
    flutterPluginBinding = binding;
  }

  /// 插件注销
  @Override
  public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
    pluginDestroy();
  }

  @Override
  public void onAttachedToActivity(ActivityPluginBinding binding) {
    pluginRegister(binding.getActivity(), flutterPluginBinding.getBinaryMessenger());
    flutterPluginBinding.getPlatformViewRegistry()
            .registerViewFactory(FACE_DETECT_CAMERA_VIEW_CHANNEL, new FaceDetectCameraFactory(
                    binding.getActivity(),
                    flutterPluginBinding.getBinaryMessenger()
            ));
  }

  @Override
  public void onDetachedFromActivity() {
    pluginDestroy();
  }

  @Override
  public void onDetachedFromActivityForConfigChanges() {
    onDetachedFromActivity();
  }

  @Override
  public void onReattachedToActivityForConfigChanges(ActivityPluginBinding binding) {
    onAttachedToActivity(binding);
  }

  // 插件注册方法
  private void pluginRegister(Activity activity, BinaryMessenger messenger) {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
      // If the sdk is less than 21 (min sdk for Camera2) we don't register the plugin.
      return;
    }
    methodCallHandler = new FacePluginMethodCallHandler(activity, messenger, METHOD_CHANNEL);
  }

  // 插件销毁
  private void pluginDestroy() {
    flutterPluginBinding = null;
    if (methodCallHandler == null) {
      // Could be on too low of an SDK to have started listening originally.
      return;
    }
    methodCallHandler.onDestroy();
    methodCallHandler = null;
  }
}


<|start_filename|>lib/face_detect_plugin.dart<|end_filename|>
import 'dart:async';

import 'package:face/model/active_file_info_model.dart';
import 'package:face/model/version_info_model.dart';
import 'package:flutter/services.dart';

import 'enum/face_detect_orient_priority_enum.dart';

class FaceDetectPlugin {
  static const MethodChannel _methodChannel = const MethodChannel('com.hs.face/method');

  /// 引擎sdk注册
  static Future<bool> activeOnLine(String appId, String sdkKey) async {
    final bool result = await _methodChannel.invokeMethod('activeOnLine',{'appId': appId, 'sdkKey': sdkKey});
    return result;
  }

  /// 获取激活文件
  static Future<ActiveFileInfoModel> getActiveFileInfo() async {
    var result = await _methodChannel.invokeMethod('getActiveFileInfo');
    ActiveFileInfoModel activeFileInfo = ActiveFileInfoModel.fromJson(result);
    return activeFileInfo;
  }

  /// 获取sdk版本
  static Future<VersionInfoModel> getSdkVersion() async {
    var result = await _methodChannel.invokeMethod('getSdkVersion');
    VersionInfoModel versionInfo = VersionInfoModel.fromJson(result);
    return versionInfo;
  }

  /// 设置视频模式检测角度设置
  static Future<void> setFaceDetectDegree(FaceDetectOrientPriorityEnum faceDetectOrientPriorityEnum) async {
    int faceDetectOrientPriority = 0;
    switch(faceDetectOrientPriorityEnum) {
      case FaceDetectOrientPriorityEnum.ASF_OP_0_ONLY:
        faceDetectOrientPriority = 1;
        break;
      case FaceDetectOrientPriorityEnum.ASF_OP_90_ONLY:
        faceDetectOrientPriority = 2;
        break;
      case FaceDetectOrientPriorityEnum.ASF_OP_270_ONLY:
        faceDetectOrientPriority = 3;
        break;
      case FaceDetectOrientPriorityEnum.ASF_OP_180_ONLY:
        faceDetectOrientPriority = 4;
        break;
      default: break;
    }
    _methodChannel.invokeMethod("setFaceDetectDegree", {"faceDetectOrientPriority": faceDetectOrientPriority});
  }
}


<|start_filename|>example/lib/face_view.dart<|end_filename|>
import 'package:flutter/material.dart';
import 'package:face/face_detect_camera_view.dart';

class CameraView extends StatefulWidget {
  @override
  _CameraViewState createState() => _CameraViewState();
}

class _CameraViewState extends State<CameraView> {

  FaceDetectCameraController faceController;

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
  }
  
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.black,
      body: Container(
        width: double.infinity,
        height: double.infinity,
        child: FaceDetectCameraView(
          showRectView: true,
          faceViewCreatedCallback: (FaceDetectCameraController faceController) {
            this.faceController = faceController
                ..faceDetectStreamListen((data) {
                  print(data.toString());
                });
          },
        ),
      ),
    );
  }

  @override
  void dispose() {
    // TODO: implement dispose
    super.dispose();
  }
}


<|start_filename|>example/lib/main.dart<|end_filename|>
import 'package:flutter/material.dart';
import 'dart:async';

import 'package:face/face_detect_plugin.dart';
import 'package:face/model/version_info_model.dart';
import 'package:face/model/active_file_info_model.dart';
import 'package:face/enum/face_detect_orient_priority_enum.dart';

import 'face_view.dart';

void main() => runApp(MyApp());

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Home(),
    );
  }
}

class Home extends StatefulWidget {
  @override
  _HomeState createState() => _HomeState();
}

class _HomeState extends State<Home> {
  String _platformVersion = 'Unknown';

  @override
  void initState() {
    super.initState();
  }

  Future<bool> activeOnLine() async {
    try {
      bool result = await FaceDetectPlugin.activeOnLine("<KEY>","<KEY>");
      return result;
    } catch (e) {
      print(e.message);
    }
  }

  Future<void> getSdkVersion() async {
    try {
      VersionInfoModel result = await FaceDetectPlugin.getSdkVersion();
      print(result.toString());
    } catch (e) {
      print(e.message);
    }
  }

  Future<void> getActiveFileInfo() async {
    try {
      ActiveFileInfoModel result = await FaceDetectPlugin.getActiveFileInfo();
      print(result.toString());
    } catch (e) {
      print(e.message);
    }
  }

  Future<void> setFaceDetectOrientPriority(FaceDetectOrientPriorityEnum faceDetectOrientPriorityEnum) async {
    try {
      await FaceDetectPlugin.setFaceDetectDegree(faceDetectOrientPriorityEnum);
      print(faceDetectOrientPriorityEnum);
      Navigator.pop(context);
    } catch (e) {
      print(e.message);
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Plugin example app'),
      ),
      body: Column(
        children: <Widget>[
          Text('Running on: $_platformVersion\n'),
          RaisedButton(
            child: Text("注册引擎"),
            onPressed: activeOnLine,
          ),
          RaisedButton(
            child: Text("获取注册信息"),
            onPressed: getActiveFileInfo,
          ),
          RaisedButton(
            child: Text("获取版本信息"),
            onPressed: getSdkVersion,
          ),
          RaisedButton(
            child: Text("设置视频人脸检测角度"),
            onPressed: () => setFaceDetectOrientPriorityView(context),
          ),
          RaisedButton(
            child: Text("相机模式人脸检测"),
            onPressed: () {
              print("打开相机");
              Navigator.push(context, MaterialPageRoute(builder: (context) => CameraView()));
            },
          )
        ],
      ),
    );
  }

  void setFaceDetectOrientPriorityView(BuildContext context) {
    showModalBottomSheet(context: context, builder: (BuildContext context) {
      return Container(
        height: 240.0,
        color: Color(0xfff1f1f1),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.center,
          children: <Widget>[
            RaisedButton(
              onPressed: () => setFaceDetectOrientPriority(FaceDetectOrientPriorityEnum.ASF_OP_0_ONLY),
              child: Text("视频模式仅检测0度"),
            ),
            RaisedButton(
              onPressed: () => setFaceDetectOrientPriority(FaceDetectOrientPriorityEnum.ASF_OP_90_ONLY),
              child: Text("视频模式仅检测90度"),
            ),
            RaisedButton(
              onPressed: () => setFaceDetectOrientPriority(FaceDetectOrientPriorityEnum.ASF_OP_180_ONLY),
              child: Text("视频模式仅检测180度"),
            ),
            RaisedButton(
              onPressed: () => setFaceDetectOrientPriority(FaceDetectOrientPriorityEnum.ASF_OP_270_ONLY),
              child: Text("视频模式仅检测270度"),
            ),
            RaisedButton(
              onPressed: () => setFaceDetectOrientPriority(FaceDetectOrientPriorityEnum.ASF_OP_ALL_OUT),
              child: Text("视频模式全方向人脸检测"),
            )
          ]
        ),
      );
    });
  }
}



<|start_filename|>lib/model/version_info_model.dart<|end_filename|>
class VersionInfoModel {
  String version;
  String buildDate;
  String copyRight;

  VersionInfoModel({
      this.version: "",
      this.buildDate: "",
      this.copyRight: ""
  });

  factory VersionInfoModel.fromJson(Map<String, dynamic> json) => VersionInfoModel(
      version: json["version"] == null ? "" : json["version"],
      buildDate: json["buildDate"] == null ? "" : json["buildDate"],
      copyRight: json["copyRight"] == null ? "" : json["copyRight"]
  );

  Map<String, dynamic> toJson() => {
    "version": version == null ? null : version,
    "buildDate": buildDate == null ? null : buildDate,
    "copyRight": copyRight == null ? null : copyRight
  };
}

<|start_filename|>lib/enum/face_detect_orient_priority_enum.dart<|end_filename|>
enum FaceDetectOrientPriorityEnum {
  ASF_OP_0_ONLY,
  ASF_OP_90_ONLY,
  ASF_OP_270_ONLY,
  ASF_OP_180_ONLY,
  ASF_OP_ALL_OUT
}