Commit 89970f75 authored by Javokhir's avatar Javokhir
Browse files

2.4.1

parent c20efd36
......@@ -2,7 +2,13 @@
All notable changes to this project will be documented in this file.
## [2.4.0] - 12 Apr, 2025
## [2.4.1] - 23 Apr, 2025
- 🔐 Added new security enhancements for data protection
- 💥 Added video identification support
- 🔨 Updated several enum values for better clarity
- 🔨 Deprecated some functions and enums (will be removed in future versions)
- 🔥 Improved overall performance and stability
## [2.3.9] - 10 Apr, 2025
......
......@@ -9,10 +9,12 @@
The MyID Android SDK supports translations for the following languages:
- Uzbek (uz) 🇺🇿
- Karakalpak (kk) 🇺🇿
- Tajik (tg) 🇹🇯
- English (en) 🇬🇧
- Russian (ru) 🇷🇺
By default, the Uzbek language is used. However, you can also call the `withLocale(Locale)`
By default, the Uzbek language is used. However, you can also call the `withLocale(MyIdLocale)`
method of the `MyIdConfig.Builder` configuration to set the language.
## Custom Organization Details
......@@ -34,23 +36,31 @@ customize following fields:
You can define custom colors inside your own `colors.xml` file:
* `myidColorPrimary`: Defines the color of SDK which guides the user through the flow
Here’s the documentation with your color definitions explained in the same style:
* `myidColorError`: Defines the color of the error buttons, icons and states
---
* `myidPrimaryButtonColor`: Defines the background color of the primary action buttons
* `myidPrimaryButtonColorDisabled`: Defines the background color of the primary disabled buttons
* `myidPrimaryButtonTextColor`: Defines the color of the text inside the primary action buttons
You can define custom colors inside your own `colors.xml` file:
* `myidPrimaryButtonTextColorDisabled`: Defines the color of the text inside the primary disabled buttons
- `myid_color_primary`: Defines the color of SDK which guides the user through the flow
- `myid_color_onPrimary`: Text or icon color displayed on top of `myid_color_primary`
- `myid_color_error`: Used for error messages, borders, or icons
- `myid_color_onError`: Text or icon color used on error backgrounds
- `myid_color_divider`: Used for dividing UI elements with subtle lines
- `myid_color_outline`: Used for borders, strokes, or outlines of components
- `myid_color_success`: Used to indicate successful actions or results
- `myid_color_progress_indicator_active`: Active progress bar or loading spinner color
- `myid_color_progress_indicator_inactive`: Background color of inactive progress indicators
- `myid_button_container_color`: Background color of enabled buttons
- `myid_button_container_disabled_color`: Background color of disabled buttons
- `myid_button_content_color`: Text/icon color on enabled buttons
- `myid_button_content_disabled_color`: Text/icon color on disabled buttons
**Widgets**
You can customize the appearance of some widgets in your `dimens.xml` file by overriding:
* `myidButtonCornerRadius`: Defines the radius dimension of all the corners of primary buttons
* `myid_button_corner_radius`: Defines the radius dimension of all the corners of primary buttons
#
......
......@@ -24,7 +24,7 @@ The SDK supports API level 21 and above
Make sure that your app meets the following requirements:
- `minSdkVersion = 21`
- `targetSdkVersion = 34`
- `targetSdkVersion = 35`
- `Kotlin = 1.8.22+`
- `android.useAndroidX = true`
......@@ -53,15 +53,7 @@ Next, add the SDK dependency to the dependencies block:
```gradle
dependencies {
implementation("uz.myid.sdk.capture:myid-capture-sdk:2.4.0")
}
```
If you are using Huawei devices, Flutter or an environment that does not support Google Play Services, use the bundled version of the SDK:
```gradle
dependencies {
implementation("uz.myid.sdk.capture:myid-capture-sdk-bundled:2.4.0")
implementation("uz.myid.sdk.capture:myid-capture-sdk:2.4.1")
}
```
......@@ -91,18 +83,18 @@ class ExampleActivity : AppCompatActivity(), MyIdResultListener {
}
private fun startMyId() {
val config = MyIdConfig.builder(clientId = /* Your client id */)
val config = MyIdConfig.Builder(clientId = /* Your client id */)
.withClientHash(/* Your clientHash */, /* Your clientHashId */)
.withPassportData(passportData)
.withBirthDate(dateOfBirth)
.withBuildMode(MyIdBuildMode.PRODUCTION)
.withEnvironment(MyIdEnvironment.Production)
.build()
val intent = client.createIntent(activity = this, config)
result.launch(intent)
}
private val result = takeUserResult(listener = this)
private val result = takeMyIdResult(listener = this)
}
```
......@@ -124,11 +116,11 @@ class ExampleActivity : AppCompatActivity(), MyIdResultListener {
}
private fun startMyId() {
val config = MyIdConfig.builder(clientId = /* Your client id */)
val config = MyIdConfig.Builder(clientId = /* Your client id */)
.withClientHash(/* Your clientHash */, /* Your clientHashId */)
.withPassportData(passportData)
.withBirthDate(dateOfBirth)
.withBuildMode(MyIdBuildMode.PRODUCTION)
.withEnvironment(MyIdEnvironment.Production)
.build()
/*
......@@ -145,51 +137,43 @@ class ExampleActivity : AppCompatActivity(), MyIdResultListener {
Method | Notes | Default
--- | --- | ---
`withClientHash(clientHash: String, clientHashId: String)` | Provided by MyID sales team | Mandatory, if using withEntryType(MyIdEntryType.AUTH)
`withPassportData(value: String)` | Passport serial number or PINFL data | Optional
`withBirthDate(value: String)` | Date of birth. Format: `dd.MM.yyyy` | Optional
`withMinAge(value: Int)` | To set a specific minimum age to use MyID service | 16
`withSdkHash(value: String)` | 32 characters long string (Note 1.2) | Optional
`withExternalId(value: String)` | 36 characters long. Should match with UUID4 regex (Note 1.3) | Optional
`withThreshold(value: Float)` | The value can be in the range of `0.55` - `0.99` | 0.55
`withBuildMode(value: MyIdBuildMode)` | Build mode (Note 1.4) | MyIdBuildMode.PRODUCTION
`withEntryType(value: MyIdEntryType)` | Customizing the SDK Entry types (Note 1.5) | MyIdEntryType.AUTH
`withResidency(value: MyIdResidentType)` | To set a specific resident type | MyIdResidentType.RESIDENT
`withLocale(value: Locale)` | To set a specific locale | Locale("uz")
`withCameraShape(value: MyIdCameraShape)` | To set a specific camera shape (Note 1.6) | MyIdCameraShape.CIRCLE
`withResolution(value: MyIdResolution)` | To set a specific camera resolution | MyIdResolution.RESOLUTION_480
`withScreenOrientation(value: MyIdScreenOrientation)` | To set a specific screen orientation | MyIdScreenOrientation.FULL
`withImageFormat(value: MyIdImageFormat)` | To set a specific image format | MyIdImageFormat.PNG
`withOrganizationDetails(value: MyIdOrganizationDetails)` | Custom Organization Details | Optional
`withClientHash(clientHash: String, clientHashId: String)` | Provided by MyID sales team | Mandatory, if using withEntryType(MyIdEntryType.Identification)
`withPassportData(passportData: String)` | Passport serial number or PINFL data | Optional
`withBirthDate(dateOfBirth: String)` | Date of birth. Format: `dd.MM.yyyy` | Optional
`withSdkHash(sdkHash: String)` | 32 characters long string (Note 1.2) | Optional
`withMinAge(age: Int)` | To set a specific minimum age to use MyID service | 16
`withExternalId(externalId: String)` | 36 characters long. Should match with UUID4 regex (Note 1.3) | Optional
`withThreshold(threshold: Float)` | The value can be in the range of `0.55` - `0.99` | 0.55
`withResidency(residency: MyIdResidency)` | To set a specific residency type | MyIdResidency.Resident
`withEnvironment(environment: MyIdEnvironment)` | Environment mode (Note 1.4) | MyIdEnvironment.Production
`withEntryType(type: MyIdEntryType)` | Customizing the SDK Entry types (Note 1.5) | MyIdEntryType.Identification
`withLocale(locale: MyIdLocale)` | To set a specific locale | MyIdLocale.Uzbek
`withCameraShape(shape: MyIdCameraShape)` | To set a specific camera shape (Note 1.6) | MyIdCameraShape.Circle
`withCameraResolution(resolution: MyIdCameraResolution)` | To set a specific camera resolution | MyIdCameraResolution.Low
`withImageFormat(format: MyIdImageFormat)` | To set a specific image format | MyIdImageFormat.PNG
`withOrganizationDetails(details: MyIdOrganizationDetails)` | Custom Organization Details | Optional
**Note 1.1.** You can customize the screen for entering passport data and date of birth in your
application, in which case you can pass these parameters during initialization to the SDK, otherwise
the SDK requires the input of passport data and date of birth for user identification.
**Note 1.2.** If the `sdk_hash` is empty, blank or string with length other than 32 has been
provided, we will continue showing the credentials screen.
**Note 1.3.** If the `externalId` is not empty, has a length of 36 characters and corresponds to the
regular expression UUID4, we will not display a [recommendation](images/screen01.jpg) screen. If a certain number of unsuccessful identification attempts (currently set to 5) occur in MyID within one hour and the `externalId` is not empty, SDK returns to the parent app error message or TTL as `message` in `MyIdException`.
**Note 1.2.** If the `sdk_hash` is empty, blank or string with length other than 32 has been provided, we will continue showing the credentials screen.
TTL error example:
```json
{"ttl": 362}
```
**Note 1.3.** If the `externalId` is not empty, has a length of 36 characters and corresponds to the regular expression UUID4, we will not display a [recommendation](images/screen01.jpg) screen. If a certain number of unsuccessful identification attempts (currently set to 5) occur in MyID within one hour and the `externalId` is not empty, SDK returns to the parent app error message as `message` in `MyIdException`.
**Note 1.4.** `MyIdBuildMode` contains **DEBUG** and **PRODUCTION** modes.
`MyIdEnvironment` contains **Debug** and **Production** modes.
- **DEBUG** is used to sandbox.
- **PRODUCTION** is used to production.
- **Debug** is used to sandbox.
- **Production** is used to production.
**Note 1.5.** `MyIdEntryType` contains **AUTH** and **FACE** types.
**Note 1.5.** `MyIdEntryType` contains **Identification**, **VideoIdentification** and **FaceDetection** types.
- **AUTH** is used to identify the user through the MyID services.
- **FACE** is used to detect a face and returns a picture (bitmap).
- **Identification** is used to identify the user through the MyID services.
- **VideoIdentification** is used to identify the user through the MyID services.
- **FaceDetection** is used to detect a face and returns a picture (bitmap).
**Note 1.6.** `MyIdCameraShape` contains **[CIRCLE](images/screen03.jpg)**
and **[ELLIPSE](images/screen04.jpg)** types.
**Note 1.6.** `MyIdCameraShape` contains **[Circle](images/screen03.jpg)**
and **[Ellipse](images/screen04.jpg)** types.
### 1.2 Handling callbacks
......@@ -198,7 +182,7 @@ val resultListener: MyIdResultListener = object : MyIdResultListener {
override fun onSuccess(result: MyIdResult) {
// Get face bitmap and result code
val bitmap = result.getGraphicFieldImageByType(MyIdGraphicFieldType.FACE_PORTRAIT)
val bitmap = result.getGraphicFieldImageByType(MyIdGraphicFieldType.FacePortrait)
val code = result.code
val comparison = result.comparison
}
......
/build
\ No newline at end of file
plugins {
id "com.android.application"
id "org.jetbrains.kotlin.android"
}
android {
namespace "uz.myid.sdk.sample"
compileSdk 34
defaultConfig {
applicationId "uz.myid.sdk.sample"
targetSdk 34
minSdk 21
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro"
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
buildFeatures {
viewBinding true
}
}
dependencies {
implementation("com.google.android.material:material:1.11.0")
implementation("uz.myid.sdk.capture:myid-capture-sdk:2.2.8")
}
\ No newline at end of file
plugins {
alias(libs.plugins.android.application)
alias(libs.plugins.kotlin.android)
}
android {
namespace = "uz.uzinfocom.myid"
compileSdk = 35
defaultConfig {
applicationId = "uz.uzinfocom.myid"
minSdk = 21
targetSdk = 35
versionCode = 1
versionName = "1.0"
}
buildTypes {
release {
isMinifyEnabled = false
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
}
}
compileOptions {
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
kotlinOptions {
jvmTarget = JavaVersion.VERSION_17.toString()
}
buildFeatures {
viewBinding = true
}
}
dependencies {
implementation(libs.androidx.core)
implementation(libs.androidx.appcompat)
implementation(libs.androidx.activity)
implementation(libs.google.material)
implementation(libs.myid)
implementation(libs.myid.video)
}
\ No newline at end of file
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.MyIdSample">
android:theme="@style/Theme.MyId">
<activity
android:name=".MainActivity"
android:exported="true">
......
package uz.myid.sdk.sample;
import static uz.myid.android.sdk.capture.MyIdResultKt.takeUserResult;
import android.content.Intent;
import android.os.Bundle;
import androidx.activity.result.ActivityResultLauncher;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import uz.myid.android.sdk.capture.MyIdClient;
import uz.myid.android.sdk.capture.MyIdConfig;
import uz.myid.android.sdk.capture.MyIdException;
import uz.myid.android.sdk.capture.MyIdResult;
import uz.myid.android.sdk.capture.MyIdResultListener;
import uz.myid.android.sdk.capture.model.MyIdBuildMode;
public class ExampleJavaActivity extends AppCompatActivity implements MyIdResultListener {
private final MyIdClient client = new MyIdClient();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
startMyId();
}
@Override
public void onSuccess(@NonNull MyIdResult result) {
// Get face bitmap, result code, comparison value
}
@Override
public void onError(@NonNull MyIdException e) {
// Get error message and code
}
@Override
public void onUserExited() {
// User exited sdk
}
private void startMyId() {
String clientId = "client_id";
String clientHash = "client_hash";
String clientHashId = "client_hash_id";
String passportData = "passport_data";
String dateOfBirth = "date_of_birth";
MyIdConfig config = new MyIdConfig.Builder(clientId)
.withClientHash(clientHash, clientHashId)
.withPassportData(passportData)
.withBirthDate(dateOfBirth)
.withBuildMode(MyIdBuildMode.PRODUCTION)
.build();
Intent intent = client.createIntent(this, config);
result.launch(intent);
}
private final ActivityResultLauncher<Intent> result = takeUserResult(this, this);
}
\ No newline at end of file
package uz.myid.sdk.sample;
import static uz.myid.android.sdk.capture.MyIdResultKt.takeUserResult;
import android.content.Intent;
import android.os.Bundle;
import androidx.activity.result.ActivityResultLauncher;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import uz.myid.android.sdk.capture.MyIdClient;
import uz.myid.android.sdk.capture.MyIdConfig;
import uz.myid.android.sdk.capture.MyIdException;
import uz.myid.android.sdk.capture.MyIdResult;
import uz.myid.android.sdk.capture.MyIdResultListener;
import uz.myid.android.sdk.capture.model.MyIdBuildMode;
public class ExampleJavaFragment extends Fragment implements MyIdResultListener {
private final MyIdClient client = new MyIdClient();
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
startMyId();
}
@Override
public void onSuccess(@NonNull MyIdResult result) {
// Get face bitmap, result code, comparison value
}
@Override
public void onError(@NonNull MyIdException e) {
// Get error message and code
}
@Override
public void onUserExited() {
// User exited sdk
}
private void startMyId() {
String clientId = "client_id";
String clientHash = "client_hash";
String clientHashId = "client_hash_id";
String passportData = "passport_data";
String dateOfBirth = "date_of_birth";
MyIdConfig config = new MyIdConfig.Builder(clientId)
.withClientHash(clientHash, clientHashId)
.withPassportData(passportData)
.withBirthDate(dateOfBirth)
.withBuildMode(MyIdBuildMode.PRODUCTION)
.build();
Intent intent = client.createIntent(requireActivity(), config);
result.launch(intent);
}
private final ActivityResultLauncher<Intent> result = takeUserResult(this, this);
}
package uz.myid.sdk.sample
import android.os.Bundle
import androidx.fragment.app.Fragment
import uz.myid.android.sdk.capture.MyIdClient
import uz.myid.android.sdk.capture.MyIdConfig
import uz.myid.android.sdk.capture.MyIdException
import uz.myid.android.sdk.capture.MyIdResult
import uz.myid.android.sdk.capture.MyIdResultListener
import uz.myid.android.sdk.capture.model.MyIdBuildMode
import uz.myid.android.sdk.capture.takeUserResult
class ExampleKotlinFragment : Fragment(), MyIdResultListener {
private val client = MyIdClient()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
startMyId()
}
override fun onSuccess(result: MyIdResult) {
// Get face bitmap and result code
}
override fun onError(e: MyIdException) {
// Get error message and code
}
override fun onUserExited() {
// User exited sdk
}
private fun startMyId() {
val clientId = "client_id"
val clientHash = "client_hash"
val clientHashId = "client_hash_id"
val passportData = "passport_data"
val dateOfBirth = "date_of_birth"
val config = MyIdConfig.Builder(clientId)
.withClientHash(clientHash, clientHashId)
.withPassportData(passportData)
.withBirthDate(dateOfBirth)
.withBuildMode(MyIdBuildMode.PRODUCTION)
.build()
val intent = client.createIntent(requireActivity(), config)
result.launch(intent)
}
private val result = takeUserResult(this)
}
\ No newline at end of file
package uz.myid.sdk.sample
import android.content.Intent
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import uz.myid.android.sdk.capture.MyIdClient
import uz.myid.android.sdk.capture.MyIdConfig
import uz.myid.android.sdk.capture.MyIdException
import uz.myid.android.sdk.capture.MyIdResult
import uz.myid.android.sdk.capture.MyIdResultListener
import uz.myid.android.sdk.capture.model.MyIdBuildMode
class ExampleWithOnActivityResultActivity : AppCompatActivity(), MyIdResultListener {
private val client = MyIdClient()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
startMyId()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
client.handleActivityResult(resultCode, this)
}
override fun onSuccess(result: MyIdResult) {
// Get face bitmap and result code
}
override fun onError(e: MyIdException) {
// Get error message and code
}
override fun onUserExited() {
// User exited sdk
}
private fun startMyId() {
val clientId = "client_id"
val clientHash = "client_hash"
val clientHashId = "client_hash_id"
val passportData = "passport_data"
val dateOfBirth = "date_of_birth"
val config = MyIdConfig.Builder(clientId)
.withClientHash(clientHash, clientHashId)
.withPassportData(passportData)
.withBirthDate(dateOfBirth)
.withBuildMode(MyIdBuildMode.PRODUCTION)
.build()
/*
Start the flow. 1 should be your request code (customize as needed).
Must be an Activity or Fragment (support library).
This request code will be important for you on onActivityResult() to identify the MyIdResultListener.
*/
client.startActivityForResult(this, 1, config)
}
}
\ No newline at end of file
package uz.myid.sdk.sample
import android.os.Bundle
import android.widget.EditText
import androidx.appcompat.app.AppCompatActivity
import uz.myid.android.sdk.capture.MyIdClient
import uz.myid.android.sdk.capture.MyIdConfig
import uz.myid.android.sdk.capture.MyIdException
import uz.myid.android.sdk.capture.MyIdResult
import uz.myid.android.sdk.capture.MyIdResultListener
import uz.myid.android.sdk.capture.model.MyIdBuildMode
import uz.myid.android.sdk.capture.model.MyIdGraphicFieldType
import uz.myid.android.sdk.capture.takeUserResult
import uz.myid.sdk.sample.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity(), MyIdResultListener {
private val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }
private val client = MyIdClient()
private var buildMode = MyIdBuildMode.PRODUCTION
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
with(binding) {
radioGroupBuildMode.setOnCheckedChangeListener { _, checkedId ->
buildMode = if (checkedId == R.id.radioProd) {
MyIdBuildMode.PRODUCTION
} else {
MyIdBuildMode.DEBUG
}
}
buttonStart.setOnClickListener { startMyId() }
}
}
override fun onSuccess(result: MyIdResult) {
val bitmap = result.getGraphicFieldImageByType(MyIdGraphicFieldType.FACE_PORTRAIT)
with(binding) {
imageResult.setImageBitmap(bitmap)
"""
Result code: ${result.code}
Comparison value: ${result.comparison}
""".trimIndent().also { textResult.text = it }
}
}
override fun onError(e: MyIdException) {
with(binding) {
imageResult.setImageBitmap(null)
"""
Result error: ${e.message}
Result error code: ${e.code}
""".trimIndent().also { textResult.text = it }
}
}
override fun onUserExited() {
with(binding) {
imageResult.setImageBitmap(null)
"User exited sdk".also { textResult.text = it }
}
}
private fun startMyId() {
val config = MyIdConfig.builder(binding.inputClientId.value)
.withClientHash(
clientHash = binding.inputClientHash.value,
clientHashId = binding.inputClientHashId.value,
)
.withPassportData(binding.inputPassportData.value)
.withBirthDate(binding.inputDate.value)
.withBuildMode(buildMode)
.build()
val intent = client.createIntent(this, config)
result.launch(intent)
}
private val result = takeUserResult(this)
private inline val EditText.value: String get() = text.toString().trim()
}
\ No newline at end of file
package uz.uzinfocom.myid
import android.widget.EditText
inline val EditText.value: String get() = text.toString().trim()
package uz.uzinfocom.myid
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import uz.myid.android.sdk.capture.MyIdClient
import uz.myid.android.sdk.capture.MyIdConfig
import uz.myid.android.sdk.capture.MyIdException
import uz.myid.android.sdk.capture.MyIdResult
import uz.myid.android.sdk.capture.MyIdResultListener
import uz.myid.android.sdk.capture.model.MyIdCameraResolution
import uz.myid.android.sdk.capture.model.MyIdCameraSelector
import uz.myid.android.sdk.capture.model.MyIdCameraShape
import uz.myid.android.sdk.capture.model.MyIdEntryType
import uz.myid.android.sdk.capture.model.MyIdEnvironment
import uz.myid.android.sdk.capture.model.MyIdGraphicFieldType
import uz.myid.android.sdk.capture.model.MyIdImageFormat
import uz.myid.android.sdk.capture.model.MyIdLocale
import uz.myid.android.sdk.capture.model.MyIdResidency
import uz.myid.android.sdk.capture.model.MyIdScreenOrientation
import uz.myid.android.sdk.capture.takeMyIdResult
import uz.uzinfocom.myid.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity(), MyIdResultListener {
private val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }
private val client = MyIdClient()
private var residency = MyIdResidency.Resident
private var environment = MyIdEnvironment.Debug
private var entryType = MyIdEntryType.Identification
private var cameraSelector = MyIdCameraSelector.Front
private var cameraResolution = MyIdCameraResolution.Low
private var cameraShape = MyIdCameraShape.Circle
private var imageFormat = MyIdImageFormat.PNG
private var locale = MyIdLocale.English
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
with(binding) {
radioGroupResidency.setOnCheckedChangeListener { _, checkedId ->
residency = when (checkedId) {
R.id.radioNonResident -> MyIdResidency.NonResident
R.id.radioUserDefined -> MyIdResidency.UserDefined
else -> MyIdResidency.Resident
}
}
radioGroupEnvironment.setOnCheckedChangeListener { _, checkedId ->
environment = if (checkedId == R.id.radioProd) {
MyIdEnvironment.Production
} else {
MyIdEnvironment.Debug
}
}
radioGroupEntryType.setOnCheckedChangeListener { _, checkedId ->
entryType = when (checkedId) {
R.id.radioPhoto -> MyIdEntryType.Identification
R.id.radioVideo -> MyIdEntryType.VideoIdentification
else -> MyIdEntryType.FaceDetection
}
}
radioGroupCameraSelector.setOnCheckedChangeListener { _, checkedId ->
cameraSelector = if (checkedId == R.id.radioFront) {
MyIdCameraSelector.Front
} else {
MyIdCameraSelector.Back
}
}
radioGroupResolution.setOnCheckedChangeListener { _, checkedId ->
cameraResolution = if (checkedId == R.id.radioHigh) {
MyIdCameraResolution.High
} else {
MyIdCameraResolution.Low
}
}
radioGroupShape.setOnCheckedChangeListener { _, checkedId ->
cameraShape = if (checkedId == R.id.radioEllipse) {
MyIdCameraShape.Ellipse
} else {
MyIdCameraShape.Circle
}
}
radioGroupImageFormat.setOnCheckedChangeListener { _, checkedId ->
imageFormat = if (checkedId == R.id.radioJpeg) {
MyIdImageFormat.JPEG
} else {
MyIdImageFormat.PNG
}
}
radioGroupLang.setOnCheckedChangeListener { _, checkedId ->
locale = when (checkedId) {
R.id.radioEn -> MyIdLocale.English
R.id.radioRu -> MyIdLocale.Russian
else -> MyIdLocale.Uzbek
}
}
buttonStart.setOnClickListener { startMyId() }
}
}
override fun onSuccess(result: MyIdResult) {
val bitmap = result.getGraphicFieldImageByType(MyIdGraphicFieldType.FacePortrait)
binding.imageResult.setImageBitmap(bitmap)
with(binding) {
"""
Result code: ${result.code}
""".trimIndent().also { textResult.text = it }
}
}
override fun onError(exception: MyIdException) {
with(binding) {
imageResult.setImageBitmap(null)
"""
Result error: ${exception.message}
Result error code: ${exception.code}
""".trimIndent().also { textResult.text = it }
}
}
override fun onUserExited() {
with(binding) {
imageResult.setImageBitmap(null)
"User exited".also { textResult.text = it }
}
}
private fun startMyId() {
val config = MyIdConfig.Builder("client_id")
.withClientHash(
clientHash = "client_hash",
clientHashId = "client_hash_id",
)
.withDocumentData(
passportData = binding.inputPassportData.value,
dateOfBirth = binding.inputDate.value,
)
.withResidency(residency)
.withEnvironment(environment)
.withEntryType(entryType)
.withCameraSelector(cameraSelector)
.withCameraResolution(cameraResolution)
.withCameraShape(cameraShape)
.withImageFormat(imageFormat)
.withScreenOrientation(MyIdScreenOrientation.Portrait)
.withLocale(locale)
.build()
val intent = client.createIntent(this, config)
result.launch(intent)
}
private val result = takeMyIdResult(this)
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
tools:context=".MainActivity">
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
......@@ -21,7 +19,7 @@
app:helperTextEnabled="true">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/inputClientId"
android:id="@+id/inputSessionId"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:importantForAutofill="no"
......@@ -39,11 +37,10 @@
app:helperTextEnabled="true">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/inputClientHash"
android:id="@+id/inputHash"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:importantForAutofill="no"
android:inputType="textMultiLine"
android:textAppearance="@style/TextAppearance.Material3.BodyLarge" />
</com.google.android.material.textfield.TextInputLayout>
......@@ -57,11 +54,10 @@
app:helperTextEnabled="true">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/inputClientHashId"
android:id="@+id/inputHashId"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:importantForAutofill="no"
android:inputType="textMultiLine"
android:textAppearance="@style/TextAppearance.Material3.BodyLarge" />
</com.google.android.material.textfield.TextInputLayout>
......@@ -90,7 +86,7 @@
android:hint="@string/birth_date"
app:helperText="* Optional"
app:helperTextEnabled="true"
app:placeholderText="дд.мм.гггг">
app:placeholderText="dd.MM.yyyy">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/inputDate"
......@@ -101,11 +97,41 @@
</com.google.android.material.textfield.TextInputLayout>
<RadioGroup
android:id="@+id/radioGroupBuildMode"
android:id="@+id/radioGroupResidency"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:checkedButton="@id/radioProd"
android:checkedButton="@id/radioResident"
android:orientation="vertical">
<RadioButton
android:id="@+id/radioResident"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/resident"
android:textAppearance="@style/TextAppearance.Material3.BodyLarge" />
<RadioButton
android:id="@+id/radioNonResident"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/non_resident"
android:textAppearance="@style/TextAppearance.Material3.BodyLarge" />
<RadioButton
android:id="@+id/radioUserDefined"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/user_defined"
android:textAppearance="@style/TextAppearance.Material3.BodyLarge" />
</RadioGroup>
<RadioGroup
android:id="@+id/radioGroupEnvironment"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:checkedButton="@id/radioDev"
android:orientation="horizontal">
<RadioButton
......@@ -124,6 +150,164 @@
android:textAppearance="@style/TextAppearance.Material3.BodyLarge" />
</RadioGroup>
<RadioGroup
android:id="@+id/radioGroupEntryType"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:checkedButton="@id/radioPhoto"
android:orientation="vertical">
<RadioButton
android:id="@+id/radioPhoto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/auth"
android:textAppearance="@style/TextAppearance.Material3.BodyLarge" />
<RadioButton
android:id="@+id/radioVideo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/video"
android:textAppearance="@style/TextAppearance.Material3.BodyLarge" />
<RadioButton
android:id="@+id/radioFace"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/face"
android:textAppearance="@style/TextAppearance.Material3.BodyLarge" />
</RadioGroup>
<RadioGroup
android:id="@+id/radioGroupCameraSelector"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:checkedButton="@id/radioFront"
android:orientation="horizontal">
<RadioButton
android:id="@+id/radioFront"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/front"
android:textAppearance="@style/TextAppearance.Material3.BodyLarge" />
<RadioButton
android:id="@+id/radioBack"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:text="@string/back"
android:textAppearance="@style/TextAppearance.Material3.BodyLarge" />
</RadioGroup>
<RadioGroup
android:id="@+id/radioGroupImageFormat"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:checkedButton="@id/radioPng"
android:orientation="horizontal">
<RadioButton
android:id="@+id/radioJpeg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/jpeg"
android:textAppearance="@style/TextAppearance.Material3.BodyLarge" />
<RadioButton
android:id="@+id/radioPng"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:text="@string/png"
android:textAppearance="@style/TextAppearance.Material3.BodyLarge" />
</RadioGroup>
<RadioGroup
android:id="@+id/radioGroupResolution"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:checkedButton="@id/radioLow"
android:orientation="horizontal">
<RadioButton
android:id="@+id/radioLow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/low"
android:textAppearance="@style/TextAppearance.Material3.BodyLarge" />
<RadioButton
android:id="@+id/radioHigh"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:text="@string/high"
android:textAppearance="@style/TextAppearance.Material3.BodyLarge" />
</RadioGroup>
<RadioGroup
android:id="@+id/radioGroupShape"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:checkedButton="@id/radioCircle"
android:orientation="horizontal">
<RadioButton
android:id="@+id/radioCircle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/circle"
android:textAppearance="@style/TextAppearance.Material3.BodyLarge" />
<RadioButton
android:id="@+id/radioEllipse"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:text="@string/ellipse"
android:textAppearance="@style/TextAppearance.Material3.BodyLarge" />
</RadioGroup>
<RadioGroup
android:id="@+id/radioGroupLang"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:checkedButton="@id/radioEn"
android:orientation="horizontal">
<RadioButton
android:id="@+id/radioUz"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/uzbek"
android:textAppearance="@style/TextAppearance.Material3.BodyLarge" />
<RadioButton
android:id="@+id/radioEn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:text="@string/english"
android:textAppearance="@style/TextAppearance.Material3.BodyLarge" />
<RadioButton
android:id="@+id/radioRu"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:text="@string/russian"
android:textAppearance="@style/TextAppearance.Material3.BodyLarge" />
</RadioGroup>
<com.google.android.material.button.MaterialButton
android:id="@+id/buttonStart"
style="@style/Widget.Material3.Button.UnelevatedButton"
......@@ -134,25 +318,29 @@
android:text="@string/scan_face_data"
android:textAppearance="@style/TextAppearance.Material3.BodyLarge" />
<TextView
android:id="@+id/textResult"
<com.google.android.material.button.MaterialButton
android:id="@+id/buttonSave"
style="@style/Widget.Material3.Button.UnelevatedButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="20dp"
android:textAppearance="@style/TextAppearance.Material3.BodyLarge" />
android:text="@string/save_to_gallery"
android:textAppearance="@style/TextAppearance.Material3.BodyLarge"
android:visibility="gone" />
<TextView
android:id="@+id/textResult"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="@string/result_image"
android:textAppearance="@style/TextAppearance.Material3.BodyLarge" />
<ImageView
android:id="@+id/imageResult"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_marginTop="16dp"
android:layout_marginTop="20dp"
android:importantForAccessibility="no" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
\ No newline at end of file
......@@ -2,4 +2,5 @@
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>
\ No newline at end of file
......@@ -2,4 +2,5 @@
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources />
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<resources>
<string name="app_name">MyID Sample</string>
<string name="birth_date">Birth date</string>
<string name="app_name">MyID SDK</string>
<string name="client_id">Client ID</string>
<string name="client_hash">Client hash</string>
<string name="client_hash_id">Client hash ID</string>
<string name="dev">Dev</string>
<string name="passport">Passport or PINFL</string>
<string name="prod">Prod</string>
<string name="result_image">Result image</string>
<string name="client_hash">Client Hash</string>
<string name="client_hash_id">Client Hash ID</string>
<string name="passport">Passport data</string>
<string name="birth_date">Date of birth</string>
<string name="prod">Production</string>
<string name="dev">Debug</string>
<string name="auth">Photo Identification</string>
<string name="video">Video Identification</string>
<string name="face">Face detection</string>
<string name="front">Front</string>
<string name="back">Back</string>
<string name="jpeg">JPEG</string>
<string name="png">PNG</string>
<string name="low">480P</string>
<string name="high">720P</string>
<string name="circle">Circle</string>
<string name="ellipse">Ellipse</string>
<string name="uzbek">Uzbek</string>
<string name="english">English</string>
<string name="russian">Russian</string>
<string name="resident">Resident</string>
<string name="non_resident">Non-resident</string>
<string name="user_defined">User defined</string>
<string name="scan_face_data">Scan face data</string>
<string name="save_to_gallery">Save to gallery</string>
</resources>
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment