From ff0e435cf7bed160f0f46c4fc804ac09d5e5388d Mon Sep 17 00:00:00 2001 From: wangzongmao Date: Tue, 6 Jul 2021 21:47:14 +0800 Subject: [PATCH 1/2] add sample for FaceRecognition Signed-off-by: wangzongmao --- security/FaceRecognition/README.md | 5 + security/FaceRecognition/README_zh.md | 6 + security/FaceRecognition/build.gradle | 34 +++++ security/FaceRecognition/entry/build.gradle | 18 +++ .../entry/src/main/config.json | 53 +++++++ .../samples/facerecognition/MainAbility.java | 32 +++++ .../slice/MainAbilitySlice.java | 131 ++++++++++++++++++ .../facerecognition/utils/ThreadPoolUtil.java | 69 +++++++++ .../main/resources/base/element/string.json | 12 ++ .../main/resources/base/graphic/button_bg.xml | 22 +++ .../resources/base/layout/dialog_layout.xml | 50 +++++++ .../base/layout/main_ability_slice.xml | 57 ++++++++ .../src/main/resources/base/media/icon.png | Bin 0 -> 6790 bytes .../screenshots/phone/fail.png | Bin 0 -> 84839 bytes .../screenshots/phone/main.png | Bin 0 -> 69526 bytes .../screenshots/phone/success.png | Bin 0 -> 79782 bytes security/FaceRecognition/settings.gradle | 1 + 17 files changed, 490 insertions(+) create mode 100644 security/FaceRecognition/README.md create mode 100644 security/FaceRecognition/README_zh.md create mode 100644 security/FaceRecognition/build.gradle create mode 100644 security/FaceRecognition/entry/build.gradle create mode 100644 security/FaceRecognition/entry/src/main/config.json create mode 100644 security/FaceRecognition/entry/src/main/java/ohos/samples/facerecognition/MainAbility.java create mode 100644 security/FaceRecognition/entry/src/main/java/ohos/samples/facerecognition/slice/MainAbilitySlice.java create mode 100644 security/FaceRecognition/entry/src/main/java/ohos/samples/facerecognition/utils/ThreadPoolUtil.java create mode 100644 security/FaceRecognition/entry/src/main/resources/base/element/string.json create mode 100644 security/FaceRecognition/entry/src/main/resources/base/graphic/button_bg.xml create mode 100644 security/FaceRecognition/entry/src/main/resources/base/layout/dialog_layout.xml create mode 100644 security/FaceRecognition/entry/src/main/resources/base/layout/main_ability_slice.xml create mode 100644 security/FaceRecognition/entry/src/main/resources/base/media/icon.png create mode 100644 security/FaceRecognition/screenshots/phone/fail.png create mode 100644 security/FaceRecognition/screenshots/phone/main.png create mode 100644 security/FaceRecognition/screenshots/phone/success.png create mode 100644 security/FaceRecognition/settings.gradle diff --git a/security/FaceRecognition/README.md b/security/FaceRecognition/README.md new file mode 100644 index 0000000000..1eef6f9986 --- /dev/null +++ b/security/FaceRecognition/README.md @@ -0,0 +1,5 @@ +# Facial Recognition + +- Currently, 2D and 3D facial recognition are supported and can be used in identity authentication scenarios such as device unlocking, application login, and payment. + + diff --git a/security/FaceRecognition/README_zh.md b/security/FaceRecognition/README_zh.md new file mode 100644 index 0000000000..c151e840c0 --- /dev/null +++ b/security/FaceRecognition/README_zh.md @@ -0,0 +1,6 @@ +# 人脸识别 + +- 当前生物特征识别支持2D人脸识别、3D人脸识别,可应用于设备解锁、应用登录、支付等身份认证场景。 + + + diff --git a/security/FaceRecognition/build.gradle b/security/FaceRecognition/build.gradle new file mode 100644 index 0000000000..e76a14f743 --- /dev/null +++ b/security/FaceRecognition/build.gradle @@ -0,0 +1,34 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. +apply plugin: 'com.huawei.ohos.app' + +ohos { + compileSdkVersion 5 + defaultConfig { + compatibleSdkVersion 4 + } +} +buildscript { + repositories { + maven { + url 'https://repo.huaweicloud.com/repository/maven/' + } + maven { + url 'https://developer.huawei.com/repo/' + } + jcenter() + } + dependencies { + classpath 'com.huawei.ohos:hap:2.4.4.2' + } +} +allprojects { + repositories { + maven { + url 'https://repo.huaweicloud.com/repository/maven/' + } + maven { + url 'https://developer.huawei.com/repo/' + } + jcenter() + } +} \ No newline at end of file diff --git a/security/FaceRecognition/entry/build.gradle b/security/FaceRecognition/entry/build.gradle new file mode 100644 index 0000000000..1324a93eda --- /dev/null +++ b/security/FaceRecognition/entry/build.gradle @@ -0,0 +1,18 @@ +apply plugin: 'com.huawei.ohos.hap' +ohos { + compileSdkVersion 5 + defaultConfig { + compatibleSdkVersion 4 + } + buildTypes { + release { + proguardOpt { + proguardEnabled false + rulesFiles 'proguard-rules.pro' + } + } + } +} +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) +} diff --git a/security/FaceRecognition/entry/src/main/config.json b/security/FaceRecognition/entry/src/main/config.json new file mode 100644 index 0000000000..945fb5632a --- /dev/null +++ b/security/FaceRecognition/entry/src/main/config.json @@ -0,0 +1,53 @@ +{ + "app": { + "bundleName": "ohos.samples.facerecognition", + "version": { + "code": 1000000, + "name": "1.0" + } + }, + "deviceConfig": {}, + "module": { + "package": "ohos.samples.facerecognition", + "name": ".MainAbility", + "reqCapabilities": [ + "video_support" + ], + "deviceType": [ + "default" + ], + "distro": { + "deliveryWithInstall": true, + "moduleName": "entry", + "moduleType": "entry", + "installationFree":false + }, + "abilities": [ + { + "skills": [ + { + "entities": [ + "entity.system.home" + ], + "actions": [ + "action.system.home" + ] + } + ], + "orientation": "portrait", + "formsEnabled": false, + "name": ".MainAbility", + "icon": "$media:icon", + "description": "$string:mainability_description", + "label": "$string:app_name", + "type": "page", + "launchType": "standard" + } + ], + "reqPermissions": [ + { + "name": "ohos.permission.ACCESS_BIOMETRIC" + } + ] + } +} \ No newline at end of file diff --git a/security/FaceRecognition/entry/src/main/java/ohos/samples/facerecognition/MainAbility.java b/security/FaceRecognition/entry/src/main/java/ohos/samples/facerecognition/MainAbility.java new file mode 100644 index 0000000000..609c187f2c --- /dev/null +++ b/security/FaceRecognition/entry/src/main/java/ohos/samples/facerecognition/MainAbility.java @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ohos.samples.facerecognition; + +import ohos.samples.facerecognition.slice.MainAbilitySlice; + +import ohos.aafwk.ability.Ability; +import ohos.aafwk.content.Intent; + +/** + * Facerecognition MainAbility + */ +public class MainAbility extends Ability { + @Override + public void onStart(Intent intent) { + super.onStart(intent); + super.setMainRoute(MainAbilitySlice.class.getName()); + } +} diff --git a/security/FaceRecognition/entry/src/main/java/ohos/samples/facerecognition/slice/MainAbilitySlice.java b/security/FaceRecognition/entry/src/main/java/ohos/samples/facerecognition/slice/MainAbilitySlice.java new file mode 100644 index 0000000000..7ee321e055 --- /dev/null +++ b/security/FaceRecognition/entry/src/main/java/ohos/samples/facerecognition/slice/MainAbilitySlice.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ohos.samples.facerecognition.slice; + +import ohos.samples.facerecognition.ResourceTable; +import ohos.samples.facerecognition.utils.ThreadPoolUtil; + +import ohos.aafwk.ability.AbilitySlice; +import ohos.aafwk.content.Intent; +import ohos.agp.components.Component; +import ohos.agp.components.LayoutScatter; +import ohos.agp.components.Text; +import ohos.agp.window.dialog.CommonDialog; +import ohos.biometrics.authentication.BiometricAuthentication; +import ohos.eventhandler.EventHandler; +import ohos.eventhandler.EventRunner; +import ohos.eventhandler.InnerEvent; + +/** + * MainAbilitySlice + */ +public class MainAbilitySlice extends AbilitySlice { + private static final int EVENT_MESSAGE_SUCCESS = 0x1000001; + + private static final int EVENT_MESSAGE_FAIL = 0x1000002; + + private static final int BA_CHECK_NOT_ENROLLED = 4; + + private Text resultText; + + private String result; + + private EventHandler handler = new EventHandler(EventRunner.current()) { + @Override + protected void processEvent(InnerEvent event) { + switch (event.eventId) { + case EVENT_MESSAGE_SUCCESS: + showDialog(result); + resultText.setText(result); + break; + case EVENT_MESSAGE_FAIL: + resultText.setText(result); + break; + } + } + }; + + private BiometricAuthentication biometricAuthentication; + + @Override + public void onStart(Intent intent) { + super.onStart(intent); + super.setUIContent(ResourceTable.Layout_main_ability_slice); + initComponents(); + } + + private void initComponents() { + resultText = (Text) findComponentById(ResourceTable.Id_result_text); + Component startButton = findComponentById(ResourceTable.Id_start); + Component cancelButton = findComponentById(ResourceTable.Id_cancel); + startButton.setClickedListener(this::startFaceUnlock); + cancelButton.setClickedListener(this::cancelRecognition); + } + + private synchronized void startFaceUnlock(Component component) { + try { + biometricAuthentication = BiometricAuthentication.getInstance(getAbility()); + int availability = biometricAuthentication.checkAuthenticationAvailability( + BiometricAuthentication.AuthType.AUTH_TYPE_BIOMETRIC_FACE_ONLY, + BiometricAuthentication.SecureLevel.SECURE_LEVEL_S2, true); + if (availability == 0) { + execAuthentication(); + } else if (availability == BA_CHECK_NOT_ENROLLED) { + result = "Face Unlock not enrolled, set up face Recognition first"; + } else { + result = "Biometric authentication not support"; + } + + } catch (IllegalAccessException e) { + result = "Face Recognition error "; + } + handler.sendEvent(EVENT_MESSAGE_FAIL); + } + + private void execAuthentication() { + ThreadPoolUtil.submit(() -> { + int authenticationAction = biometricAuthentication.execAuthenticationAction( + BiometricAuthentication.AuthType.AUTH_TYPE_BIOMETRIC_FACE_ONLY, + BiometricAuthentication.SecureLevel.SECURE_LEVEL_S4, true, false, null); + if (authenticationAction == 0) { + result = "Unlocked successfully"; + handler.sendEvent(EVENT_MESSAGE_SUCCESS); + } else { + result = "Authentication failed, face biometric doesn't match"; + handler.sendEvent(EVENT_MESSAGE_FAIL); + } + }); + } + + private void cancelRecognition(Component component) { + if (biometricAuthentication != null) { + biometricAuthentication.cancelAuthenticationAction(); + } + } + + private void showDialog(String message) { + Component container = LayoutScatter.getInstance(this).parse(ResourceTable.Layout_dialog_layout, null, false); + Text content = (Text) container.findComponentById(ResourceTable.Id_message); + content.setText("Recognition result:" + System.lineSeparator() + message); + CommonDialog commonDialog = new CommonDialog(this); + commonDialog.setSize(900, 400); + commonDialog.setCornerRadius(30); + commonDialog.setContentCustomComponent(container); + commonDialog.show(); + Component btnOk = container.findComponentById(ResourceTable.Id_btn_ok); + btnOk.setClickedListener(component -> commonDialog.hide()); + } +} diff --git a/security/FaceRecognition/entry/src/main/java/ohos/samples/facerecognition/utils/ThreadPoolUtil.java b/security/FaceRecognition/entry/src/main/java/ohos/samples/facerecognition/utils/ThreadPoolUtil.java new file mode 100644 index 0000000000..55b2df2140 --- /dev/null +++ b/security/FaceRecognition/entry/src/main/java/ohos/samples/facerecognition/utils/ThreadPoolUtil.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package ohos.samples.facerecognition.utils; + +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Global thread pool + */ +public class ThreadPoolUtil { + private static final int CORE_COUNT = 10; + + private static final int THREAD_COUNT = 20; + + private static final int WORK_QUEUE_SIZE = 50; + + private static final long KEEP_ALIVE = 10L; + + private static final AtomicInteger THREAD_ID = new AtomicInteger(1); + + private static ThreadPoolExecutor executor = new ThreadPoolExecutor(CORE_COUNT, THREAD_COUNT, KEEP_ALIVE, + TimeUnit.SECONDS, new ArrayBlockingQueue<>(WORK_QUEUE_SIZE), new CommonThreadFactory()); + + private ThreadPoolUtil() { + } + + /** + * Submit task to execute + * + * @param task runnable task + */ + public static void submit(Runnable task) { + executor.submit(task); + } + + /** + * ThreadFactory + * + */ + static class CommonThreadFactory implements ThreadFactory { + @Override + public Thread newThread(Runnable runnable) { + String threadName = null; + if (THREAD_ID.get() == Integer.MAX_VALUE) { + threadName = "threadpool-common-" + THREAD_ID.getAndSet(1); + } else { + threadName = "threadpool-common-" + THREAD_ID.incrementAndGet(); + } + return new Thread(runnable, threadName); + } + } +} diff --git a/security/FaceRecognition/entry/src/main/resources/base/element/string.json b/security/FaceRecognition/entry/src/main/resources/base/element/string.json new file mode 100644 index 0000000000..5616ce7d89 --- /dev/null +++ b/security/FaceRecognition/entry/src/main/resources/base/element/string.json @@ -0,0 +1,12 @@ +{ + "string": [ + { + "name": "app_name", + "value": "FaceRecognition" + }, + { + "name": "mainability_description", + "value": "hap sample empty page" + } + ] +} \ No newline at end of file diff --git a/security/FaceRecognition/entry/src/main/resources/base/graphic/button_bg.xml b/security/FaceRecognition/entry/src/main/resources/base/graphic/button_bg.xml new file mode 100644 index 0000000000..f4a9803534 --- /dev/null +++ b/security/FaceRecognition/entry/src/main/resources/base/graphic/button_bg.xml @@ -0,0 +1,22 @@ + + + + + + \ No newline at end of file diff --git a/security/FaceRecognition/entry/src/main/resources/base/layout/dialog_layout.xml b/security/FaceRecognition/entry/src/main/resources/base/layout/dialog_layout.xml new file mode 100644 index 0000000000..92119f692a --- /dev/null +++ b/security/FaceRecognition/entry/src/main/resources/base/layout/dialog_layout.xml @@ -0,0 +1,50 @@ + + + + + + + + +