diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000000000000000000000000000000000000..07f4fdb65574a91a56e488f586d83c80210cb091 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,72 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +## [2.1.4] - 21 Feb, 2023 + +### New features + +- Added new `withResidency(value: MyIdResidentType)` method for residency. +- Added new translations to texts in MyID SDK. + +## [2.1.3] - 30 Jan, 2023 + +### New features + +- Added an option to handle result on `onActivityResult` method. For more information, please visit our [README](README.md#with-onactivityresult-method). +- Added Content-Language for every request. + +### Changed features + +- UI: Increased image compression quality parameter. +- UI: Improved Auth screen ui components + +## [2.1.2] - 25 Nov, 2022 + +### New features + +- 📝 Added new identification recommendations. +- 🌟 Updated ID Card detection frame. +- 🔥 Added new `withCameraShape(value: MyIdCameraShape)` method to change camera shape. +- 🌟 Added new `withSdkHash(value: String)` method for identification. + +### Changed features + +- Update `targetSdkVersion` from `31` to `33` +- Update `androidx.core:core-ktx` from `1.8.0` to `1.9.0` +- Update `androidx.appcompat:appcompat` from `1.4.2` to `1.5.1` +- Update `cameraVersion` from `1.2.0-alpha01` to `1.3.0-alpha01` +- Update `mlkit-face-detection` from `17.0.1` to `17.1.0` +- Update `mlkit-text-recognition` from `18.0.0` to `18.0.2` +- Update `mlkit-barcode-scanning` from `18.0.0` to `18.1.0` + +## [2.1.1] - 31 Oct, 2022 + +### Changed features + +- Update `withLocale(value: MyIdLocale)` from `MyIdLocale` to `Locale` + +## [2.1.0] - 16 Sep, 2022 + +### New features + +- 🔥 Added new `withOrganizationDetails(value: OrganizationDetails)` method. You can customize the + SDK, for it to match your organization's brand + book. [Usage](README.md#custom-organization-details) +- 🌟 Added `comparison` value to the `MyIdResult` object on successful identification. + +### Fixes + +- 🔨 First April bug fixed. + +## [2.0.9] - 30 Aug, 2022 + +### New features + +- 🌟 Added new `withThreshold(value: Float)` method for identification. +- 🔥 Added Ban user feature. +- 🔥 Added Liveness fail and Bad or blurry recommendations. + +### Fixes + +- 🔨 `Image's size must be lower than 1600 kb`. This bug fixed. diff --git a/README.md b/README.md new file mode 100644 index 0000000000000000000000000000000000000000..7f4331726cd27fa1c4fdbac36fc092ae92cbd922 --- /dev/null +++ b/README.md @@ -0,0 +1,329 @@ +# MyID Android SDK + +## Table of contents + +- [Important](#important) +- [Getting started](#getting-started) + - [Before you begin](#11-before-you-begin) + - [Setup MyID Android SDK](#12-setup-myid-android-sdk) + - [Permissions](#13-permissions) +- [Usage](#usage) + - [Methods](#11-methods) + - [Handling callbacks](#12-handling-callbacks) +- [SDK error codes](#sdk-error-codes) +- [Localization](#localization) +- [Custom Organization Details](#custom-organization-details) + +## Important + +**Note:** When you update the version of MyID SDK in your application, check the version of the +libraries in [dependencies](#12-setup-myid-android-sdk) and update them too! + +## Getting started + +### 1.1 Before you begin + +Install or update Android Studio to its latest version. + +The SDK supports API level 21 and above + +Make sure that your app meets the following requirements: + +- `minSdkVersion = 21` +- `targetSdkVersion = 33` +- `android.useAndroidX = true` + +``` gradle +compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 +} +``` + +- myid-sdk-***.aar, has been provided to you, it contains SDK public interface and implementation. + Archive name contains ever increasing release version number. + +### 1.2 Setup MyID Android SDK + +Create new project in AndroidStudio. Inside mobile application folder create new folder to store SDK +libraries (For example libs) and copy MyID SDK provided libraries. + +Add reference to library to module **_build.gradle_**: + +``` gradle +implementation(files("libs/myid-sdk-2.1.4-release.aar")) +``` + +**Note:** You can get `myid-sdk-2.1.4-release.aar` file +from [here](android-sample/app/libs/myid-sdk-2.1.4-release.aar) + +After synchronization, You should be able to access to SDK classes from your source code. + +MyID Android SDK also requires following libraries to be added: + +``` gradle +dependencies { + implementation(files("libs/myid-sdk-2.1.4-release.aar")) + + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4") + + implementation("androidx.core:core-ktx:1.9.0") + implementation("androidx.appcompat:appcompat:1.5.1") + implementation("androidx.constraintlayout:constraintlayout:2.1.4") + implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1") + implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.5.1") + + def cameraVersion = "1.3.0-alpha01" + implementation("androidx.camera:camera-camera2:$cameraVersion") + implementation("androidx.camera:camera-lifecycle:$cameraVersion") + implementation("androidx.camera:camera-view:$cameraVersion") + + implementation("io.ktor:ktor-client-android:2.1.2") + implementation("io.sentry:sentry-android:6.7.0-alpha.1") + + // Use these dependencies if your app supports Google Play Services + implementation("com.google.android.gms:play-services-mlkit-face-detection:17.1.0") + implementation("com.google.android.gms:play-services-mlkit-text-recognition:18.0.2") + implementation("com.google.android.gms:play-services-mlkit-barcode-scanning:18.1.0") + + // Use these dependencies if your app doesn't support Google Play Services + implementation("com.google.mlkit:face-detection:16.1.5") + implementation("com.google.mlkit:text-recognition:16.0.0-beta6") + implementation("com.google.mlkit:barcode-scanning:17.0.2") +} +``` + +### 1.3 Permissions + +Add following lines to the **_AndroidManifest.xml_**: + +``` xml + + +``` + +## Usage + +### With Activity Result API + +``` kotlin +class ExampleActivity : AppCompatActivity(), MyIdResultListener { + + private val myIdClient = MyIdClient() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + startMyId() + } + + private fun startMyId() { + val organizationDetails = OrganizationDetails( + phoneNumber = "1234567", + logo = R.drawable.image_logo + ) + + val myIdConfig = MyIdConfig.builder(clientId = /* Your client id */) + .withPassportData(passportData) + .withBirthDate(dateOfBirth) + .withSdkHash(sdkHash) + .withExternalId(externalId) + .withThreshold(threshold) + .withBuildMode(MyIdBuildMode.PRODUCTION) + .withEntryType(MyIdEntryType.AUTH) + .withResidency(MyIdResidentType.RESIDENT) + .withLocale(Locale("en")) + .withCameraShape(MyIdCameraShape.CIRCLE) + .withOrganizationDetails(organizationDetails) + .withPhoto(false) + .build() + + val intent = client.createIntent(activity = this, myIdConfig = myIdConfig) + result.launch(intent) + } + + private val result = takeUserResult(listener = this) +} +``` + +### With `onActivityResult` method + +``` kotlin +class ExampleActivity : AppCompatActivity(), MyIdResultListener { + + private val myIdClient = MyIdClient() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + startMyId() + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) + myIdClient.handleActivityResult(resultCode, this) + } + + private fun startMyId() { + val organizationDetails = OrganizationDetails( + phoneNumber = "1234567", + logo = R.drawable.image_logo + ) + + val myIdConfig = MyIdConfig.builder(clientId = /* Your client id */) + .withPassportData(passportData) + .withBirthDate(dateOfBirth) + .withSdkHash(sdkHash) + .withExternalId(externalId) + .withThreshold(threshold) + .withBuildMode(MyIdBuildMode.PRODUCTION) + .withEntryType(MyIdEntryType.AUTH) + .withResidency(MyIdResidentType.RESIDENT) + .withLocale(Locale("en")) + .withCameraShape(MyIdCameraShape.CIRCLE) + .withOrganizationDetails(organizationDetails) + .withPhoto(false) + .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. + */ + myIdClient.startActivityForResult(this, 1, myIdConfig) + } +} +``` + +### 1.1 Methods + +Method | Notes | Default +--- | --- | --- +`withPassportData(value: String)` | Passport serial number or PINFL data | Optional +`withBirthDate(value: String)` | Date of birth in. Format: `dd.MM.yyyy` | Optional +`withSdkHash(value: String)` | 32 characters long string | Optional +`withExternalId(value: String)` | 36 characters long. Should match with UUID4 regex | Optional +`withThreshold(value: Float)` | The value can be in the range of `0.50` - `0.99` | 0.50 +`withBuildMode(value: MyIdBuildMode)` | Build mode | MyIdBuildMode.PRODUCTION +`withEntryType(value: MyIdEntryType)` | Customizing the SDK Entry types | 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 | MyIdCameraShape.CIRCLE +`withOrganizationDetails(value: OrganizationDetails)` | Custom Organization Details | Optional +`withPhoto(value: Boolean)` | Return SDK face bitmap | false + +**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 display a [recommendation](images/screen01.jpg) screen in case the +sdk detects a blurry photo. + +**Note 1.4.** `MyIdBuildMode` contains **DEBUG** and **PRODUCTION** modes. + +- **DEBUG** is used to sandbox. +- **PRODUCTION** is used to production. + +**Note 1.5.** `MyIdEntryType` contains **AUTH** and **FACE** types. + +- **AUTH** is used to identify the user through the MyID services. +- **FACE** 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. + +### 1.2 Handling callbacks + +```kotlin +val myIdResultListener: MyIdResultListener = object : MyIdResultListener { + override fun onSuccess(result: MyIdResult) { + // Get face bitmap and result code + + val bitmap = result.bitmap + val code = result.code + val comparison = result.comparison + } + + override fun onUserExited() { + // User left the SDK + } + + override fun onError(e: MyIdException) { + // Get error message and code: + + val message = e.message + val code = e.code + } +} +``` + +| Attribute | Notes | +| -----|-------| +| `onSuccess` | `MyIdResult` contains information about the face captures made during the flow, result code and comparison value. | +| `onUserExited` | User left the SDK flow without completing it. | +| `onError` | Some error happened. `MyIdException` contains information about the error message and code | + +## SDK error codes + +The error code in the following list may appear during the call of SDK. The list below is for your +reference. + +| Code | Error message +|:----:|:------------- +| 2 | Паспортные данные введены неправильно +| 3 | Не удалось подтвердить жизненность +| 4 | Не удалось распознать +| 5 | Внешний сервис недоступен или работает некорректно +| 6 | Запрашиваемый пользовател скончался +| 7 | Фото с ресурсов не получено +| 8 | Внутренняя ошибка MyID +| 9 | Срок выполнения задачи истек +| 10 | Срок ожидания задачи в очереди истек +| 11 | Сервис MyID не может обработать запрос. Попробуйте повторить позже +| 12 | Сервис MyID не может обработать запрос. Попробуйте повторить позже +| 13 | Сервис MyID не может обработать запрос. Попробуйте повторить позже +| 14 | Не удалось подтвердить жизненность. Некорректная фотография +| 15 | Сервис MyID не может обработать запрос. Попробуйте повторить позже +| 16 | Сервис MyID не может обработать запрос. Попробуйте повторить позже +| 17 | Не удалось распознать. Некорректная фотография +| 18 | Сервис проверки жизненности не может обработать запрос +| 19 | Сервис распознования не может обработать запрос +| 20 | Размытая фотография +| 21 | Лицо не полностью изображено +| 22 | Обнаружено несколько лиц +| 23 | Представленное изображение в градациях серого, требуется цветное изображение +| 24 | Обнаружены затемненные очки +| 25 | Тип фотографии не поддерживается +| 26 | Глаза закрыты либо не видны +| 27 | Обнаружено вращение головы +| 28 | Не удалось обнаружить все ориентиры +| 101 | Непредвиденная ошибка +| 102 | Доступ к камере запрещен +| 103 | Ошибка при получении данных с сервера +| 120 | Размытое фото обнаружено в SDK + +## Localization + +The MyID Android SDK supports translations for the following languages: + +- Uzbek (uz) 🇺🇿 +- English (en) 🇬🇧 +- Russian (ru) 🇷🇺 + +By default, the Uzbek language is used. However, you can also call the `withLocale(Locale)` +method of the `MyIdConfig.Builder` configuration to set the language. + +## Custom Organization Details + +You can customize the SDK, for it to match your organization's brand book, by +providing `OrganizationDetails` object to `withOrganizationDetails` method. The object allows you to +customize following fields: + +- *phoneNumber* - by default 712022202, which is MyID's call center. If you would like the customer + to call your own call center, you can display your own phone number on the error screen, by + providing it in this field ([sample](images/screen01.jpg)). +- *logo* - the drawable asset, that will be displayed on the input screen. If you would like to + display your own logo on the top of the screen, this is the place to provide it. Make sure it fits + the imageView element, which has the *240x60* size. diff --git a/android-sample/app/build.gradle b/android-sample/app/build.gradle new file mode 100644 index 0000000000000000000000000000000000000000..55e3e5eed1ef45c2065b3c091900095ea30cef3c --- /dev/null +++ b/android-sample/app/build.gradle @@ -0,0 +1,63 @@ +plugins { + id "com.android.application" + id "org.jetbrains.kotlin.android" +} + +android { + compileSdk 33 + + defaultConfig { + applicationId "uz.myid.sdk.sample" + minSdk 21 + targetSdk 33 + versionCode 1 + versionName "1.0.0" + } + + buildTypes { + debug { + minifyEnabled false + proguardFiles getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro" + } + release { + minifyEnabled true + shrinkResources 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(files("libs/myid-sdk-2.1.4-release.aar")) + + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4") + + implementation("androidx.core:core-ktx:1.9.0") + implementation("androidx.appcompat:appcompat:1.5.1") + implementation("androidx.constraintlayout:constraintlayout:2.1.4") + implementation("androidx.lifecycle:lifecycle-viewmodel-ktx:2.5.1") + implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.5.1") + + def cameraVersion = "1.3.0-alpha01" + implementation("androidx.camera:camera-camera2:$cameraVersion") + implementation("androidx.camera:camera-lifecycle:$cameraVersion") + implementation("androidx.camera:camera-view:$cameraVersion") + + implementation("io.ktor:ktor-client-android:2.1.2") + implementation("io.sentry:sentry-android:6.7.0-alpha.1") + + implementation("com.google.android.gms:play-services-mlkit-face-detection:17.1.0") + implementation("com.google.android.gms:play-services-mlkit-text-recognition:18.0.2") + implementation("com.google.android.gms:play-services-mlkit-barcode-scanning:18.1.0") + + implementation("com.google.android.material:material:1.8.0") +} \ No newline at end of file diff --git a/android-sample/app/libs/myid-sdk-2.1.4-release.aar b/android-sample/app/libs/myid-sdk-2.1.4-release.aar new file mode 100644 index 0000000000000000000000000000000000000000..9432a167c0af6bdf0593b050827c455a7e4195cc Binary files /dev/null and b/android-sample/app/libs/myid-sdk-2.1.4-release.aar differ diff --git a/android-sample/app/proguard-rules.pro b/android-sample/app/proguard-rules.pro new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/android-sample/app/src/main/AndroidManifest.xml b/android-sample/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000000000000000000000000000000000000..27f5117db13a4024210a250b97c170bdf8c20cff --- /dev/null +++ b/android-sample/app/src/main/AndroidManifest.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/android-sample/app/src/main/java/uz/myid/sdk/sample/ExampleJavaActivity.java b/android-sample/app/src/main/java/uz/myid/sdk/sample/ExampleJavaActivity.java new file mode 100644 index 0000000000000000000000000000000000000000..fe015dc2ba5c6490720e54b4a6f63776d16540f0 --- /dev/null +++ b/android-sample/app/src/main/java/uz/myid/sdk/sample/ExampleJavaActivity.java @@ -0,0 +1,76 @@ +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 java.util.Locale; + +import uz.myid.android.sdk.capture.MyIdBuildMode; +import uz.myid.android.sdk.capture.MyIdCameraShape; +import uz.myid.android.sdk.capture.MyIdClient; +import uz.myid.android.sdk.capture.MyIdConfig; +import uz.myid.android.sdk.capture.MyIdEntryType; +import uz.myid.android.sdk.capture.MyIdException; +import uz.myid.android.sdk.capture.MyIdResidentType; +import uz.myid.android.sdk.capture.MyIdResult; +import uz.myid.android.sdk.capture.MyIdResultListener; + +public class ExampleJavaActivity extends AppCompatActivity implements MyIdResultListener { + + private final MyIdClient myIdClient = 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 passportData = "passport_data"; + String dateOfBirth = "date_of_birth"; + String sdkHash = "sdk_hash"; + String externalId = "external_id"; + float threshold = 0.5f; + + MyIdConfig myIdConfig = new MyIdConfig.Builder(clientId) + .withPassportData(passportData) + .withBirthDate(dateOfBirth) + .withSdkHash(sdkHash) + .withExternalId(externalId) + .withThreshold(threshold) + .withBuildMode(MyIdBuildMode.PRODUCTION) + .withEntryType(MyIdEntryType.AUTH) + .withResidency(MyIdResidentType.RESIDENT) + .withLocale(new Locale("en")) + .withCameraShape(MyIdCameraShape.CIRCLE) + .withPhoto(false) + .build(); + + Intent intent = myIdClient.createIntent(this, myIdConfig); + result.launch(intent); + } + + private final ActivityResultLauncher result = takeUserResult(this, this); +} \ No newline at end of file diff --git a/android-sample/app/src/main/java/uz/myid/sdk/sample/ExampleJavaFragment.java b/android-sample/app/src/main/java/uz/myid/sdk/sample/ExampleJavaFragment.java new file mode 100644 index 0000000000000000000000000000000000000000..2e02eb110ca23ef1a554c237599ef16c09a78159 --- /dev/null +++ b/android-sample/app/src/main/java/uz/myid/sdk/sample/ExampleJavaFragment.java @@ -0,0 +1,76 @@ +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 java.util.Locale; + +import uz.myid.android.sdk.capture.MyIdBuildMode; +import uz.myid.android.sdk.capture.MyIdCameraShape; +import uz.myid.android.sdk.capture.MyIdClient; +import uz.myid.android.sdk.capture.MyIdConfig; +import uz.myid.android.sdk.capture.MyIdEntryType; +import uz.myid.android.sdk.capture.MyIdException; +import uz.myid.android.sdk.capture.MyIdResidentType; +import uz.myid.android.sdk.capture.MyIdResult; +import uz.myid.android.sdk.capture.MyIdResultListener; + +public class ExampleJavaFragment extends Fragment implements MyIdResultListener { + + private final MyIdClient myIdClient = 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 passportData = "passport_data"; + String dateOfBirth = "date_of_birth"; + String sdkHash = "sdk_hash"; + String externalId = "external_id"; + float threshold = 0.5f; + + MyIdConfig myIdConfig = new MyIdConfig.Builder(clientId) + .withPassportData(passportData) + .withBirthDate(dateOfBirth) + .withSdkHash(sdkHash) + .withExternalId(externalId) + .withThreshold(threshold) + .withBuildMode(MyIdBuildMode.PRODUCTION) + .withEntryType(MyIdEntryType.AUTH) + .withResidency(MyIdResidentType.RESIDENT) + .withLocale(new Locale("en")) + .withCameraShape(MyIdCameraShape.CIRCLE) + .withPhoto(false) + .build(); + + Intent intent = myIdClient.createIntent(requireActivity(), myIdConfig); + result.launch(intent); + } + + private final ActivityResultLauncher result = takeUserResult(this, this); +} diff --git a/android-sample/app/src/main/java/uz/myid/sdk/sample/ExampleKotlinFragment.kt b/android-sample/app/src/main/java/uz/myid/sdk/sample/ExampleKotlinFragment.kt new file mode 100644 index 0000000000000000000000000000000000000000..c1bed80b15ba731a89bd06d48da271f72a87f326 --- /dev/null +++ b/android-sample/app/src/main/java/uz/myid/sdk/sample/ExampleKotlinFragment.kt @@ -0,0 +1,62 @@ +package uz.myid.sdk.sample + +import android.os.Bundle +import androidx.fragment.app.Fragment +import uz.myid.android.sdk.capture.* +import uz.myid.android.sdk.capture.model.OrganizationDetails +import java.util.* + +class ExampleKotlinFragment : Fragment(), MyIdResultListener { + + private val myIdClient = 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 passportData = "passport_data" + val dateOfBirth = "date_of_birth" + val sdkHash = "sdk_hash" + val externalId = "external_id" + val threshold = 0.50f + + val organizationDetails = OrganizationDetails( + phoneNumber = "1234567", + ) + + val myIdConfig = MyIdConfig.Builder(clientId) + .withPassportData(passportData) + .withBirthDate(dateOfBirth) + .withSdkHash(sdkHash) + .withExternalId(externalId) + .withThreshold(threshold) + .withBuildMode(MyIdBuildMode.PRODUCTION) + .withEntryType(MyIdEntryType.AUTH) + .withResidency(MyIdResidentType.RESIDENT) + .withLocale(Locale("en")) + .withCameraShape(MyIdCameraShape.CIRCLE) + .withOrganizationDetails(organizationDetails) + .withPhoto(false) + .build() + + val intent = myIdClient.createIntent(requireActivity(), myIdConfig) + result.launch(intent) + } + + private val result = takeUserResult(this) +} \ No newline at end of file diff --git a/android-sample/app/src/main/java/uz/myid/sdk/sample/ExampleWithOnActivityResultActivity.kt b/android-sample/app/src/main/java/uz/myid/sdk/sample/ExampleWithOnActivityResultActivity.kt new file mode 100644 index 0000000000000000000000000000000000000000..b27fb8d5c027706e243f010fddface0553dfbce5 --- /dev/null +++ b/android-sample/app/src/main/java/uz/myid/sdk/sample/ExampleWithOnActivityResultActivity.kt @@ -0,0 +1,70 @@ +package uz.myid.sdk.sample + +import android.content.Intent +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import uz.myid.android.sdk.capture.* +import uz.myid.android.sdk.capture.model.OrganizationDetails +import java.util.* + +class ExampleWithOnActivityResultActivity : AppCompatActivity(), MyIdResultListener { + + private val myIdClient = MyIdClient() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + startMyId() + } + + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + super.onActivityResult(requestCode, resultCode, data) + myIdClient.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 passportData = "passport_data" + val dateOfBirth = "date_of_birth" + val sdkHash = "sdk_hash" + val externalId = "external_id" + val threshold = 0.50f + + val organizationDetails = OrganizationDetails( + phoneNumber = "1234567", + ) + + val myIdConfig = MyIdConfig.Builder(clientId) + .withPassportData(passportData) + .withBirthDate(dateOfBirth) + .withSdkHash(sdkHash) + .withExternalId(externalId) + .withThreshold(threshold) + .withBuildMode(MyIdBuildMode.PRODUCTION) + .withEntryType(MyIdEntryType.AUTH) + .withResidency(MyIdResidentType.RESIDENT) + .withLocale(Locale("en")) + .withCameraShape(MyIdCameraShape.CIRCLE) + .withOrganizationDetails(organizationDetails) + .withPhoto(false) + .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. + */ + myIdClient.startActivityForResult(this, 1, myIdConfig) + } +} \ No newline at end of file diff --git a/android-sample/app/src/main/java/uz/myid/sdk/sample/MainActivity.kt b/android-sample/app/src/main/java/uz/myid/sdk/sample/MainActivity.kt new file mode 100644 index 0000000000000000000000000000000000000000..7a84c0fb966ad6b22fc0581354ab6ac479aa49c8 --- /dev/null +++ b/android-sample/app/src/main/java/uz/myid/sdk/sample/MainActivity.kt @@ -0,0 +1,135 @@ +package uz.myid.sdk.sample + +import android.os.Bundle +import android.widget.EditText +import androidx.appcompat.app.AppCompatActivity +import uz.myid.android.sdk.capture.* +import uz.myid.android.sdk.capture.model.OrganizationDetails +import uz.myid.sdk.sample.databinding.ActivityMainBinding +import java.util.* + +class MainActivity : AppCompatActivity(), MyIdResultListener { + + private val binding by lazy { ActivityMainBinding.inflate(layoutInflater) } + + private val myIdClient = MyIdClient() + + private var clientId = "" + private var buildMode = MyIdBuildMode.PRODUCTION + private var entryType = MyIdEntryType.AUTH + private var residency = MyIdResidentType.RESIDENT + private var locale = Locale("en") + private var shape = MyIdCameraShape.CIRCLE + + private var code = "" + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContentView(binding.root) + + with(binding) { + inputClientId.setText(clientId) + + radioGroupLang.setOnCheckedChangeListener { _, checkedId -> + locale = when (checkedId) { + R.id.radioUz -> Locale("uz") + R.id.radioEn -> Locale("en") + else -> Locale("ru") + } + } + radioGroupEntryType.setOnCheckedChangeListener { _, checkedId -> + entryType = if (checkedId == R.id.radioFace) { + MyIdEntryType.FACE + } else { + MyIdEntryType.AUTH + } + } + radioGroupResidentType.setOnCheckedChangeListener { _, checkedId -> + residency = when (checkedId) { + R.id.radioManual -> MyIdResidentType.USER_DEFINED + R.id.radioNonResident -> MyIdResidentType.NON_RESIDENT + else -> MyIdResidentType.RESIDENT + } + } + radioGroupBuildMode.setOnCheckedChangeListener { _, checkedId -> + buildMode = if (checkedId == R.id.radioProd) { + MyIdBuildMode.PRODUCTION + } else { + MyIdBuildMode.DEBUG + } + + inputClientId.setText(clientId) + } + radioGroupShape.setOnCheckedChangeListener { _, checkedId -> + shape = if (checkedId == R.id.radioCircle) { + MyIdCameraShape.CIRCLE + } else { + MyIdCameraShape.ELLIPSE + } + } + + buttonStart.setOnClickListener { startMyId() } + } + } + + override fun onSuccess(result: MyIdResult) { + code = result.code.orEmpty() + + with(binding) { + imageResult.setImageBitmap(result.bitmap) + """ + Result code: ${result.code} + Comparison value: ${result.comparison} + """.trimIndent().also { textResult.text = it } + } + } + + override fun onError(e: MyIdException) { + code = "" + + with(binding) { + imageResult.setImageBitmap(null) + """ + Result error: ${e.message} + Result error code: ${e.code} + """.trimIndent().also { textResult.text = it } + } + } + + override fun onUserExited() { + code = "" + + with(binding) { + imageResult.setImageBitmap(null) + "User exited sdk".also { textResult.text = it } + } + } + + private fun startMyId() { + val organizationDetails = OrganizationDetails( + phoneNumber = binding.inputPhoneNumber.value + ) + + val myIdConfig = MyIdConfig.builder(binding.inputClientId.value) + .withPassportData(binding.inputPassportData.value) + .withBirthDate(binding.inputDate.value) + .withSdkHash(binding.inputSdkHash.value) + .withExternalId(binding.inputExternalId.value) + .withThreshold(binding.thresholdSlider.value) + .withBuildMode(buildMode) + .withEntryType(entryType) + .withResidency(residency) + .withLocale(locale) + .withCameraShape(shape) + .withOrganizationDetails(organizationDetails) + .withPhoto(binding.checkboxWithPhoto.isChecked) + .build() + + val intent = myIdClient.createIntent(this, myIdConfig) + result.launch(intent) + } + + private val result = takeUserResult(this) + + private inline val EditText.value: String get() = text.toString().trim() +} \ No newline at end of file diff --git a/android-sample/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/android-sample/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000000000000000000000000000000000000..2b068d11462a4b96669193de13a711a3a36220a0 --- /dev/null +++ b/android-sample/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/android-sample/app/src/main/res/drawable/ic_launcher_background.xml b/android-sample/app/src/main/res/drawable/ic_launcher_background.xml new file mode 100644 index 0000000000000000000000000000000000000000..07d5da9cbf141911847041df5d7b87f0dd5ef9d4 --- /dev/null +++ b/android-sample/app/src/main/res/drawable/ic_launcher_background.xml @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android-sample/app/src/main/res/layout/activity_main.xml b/android-sample/app/src/main/res/layout/activity_main.xml new file mode 100644 index 0000000000000000000000000000000000000000..a4bad87b28c4d6bf49e66cc71a9fca4d9ee6cb6c --- /dev/null +++ b/android-sample/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,313 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/android-sample/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/android-sample/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000000000000000000000000000000000000..eca70cfe52eac1ba66ba280a68ca7be8fcf88a16 --- /dev/null +++ b/android-sample/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/android-sample/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/android-sample/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000000000000000000000000000000000000..eca70cfe52eac1ba66ba280a68ca7be8fcf88a16 --- /dev/null +++ b/android-sample/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/android-sample/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/android-sample/app/src/main/res/mipmap-hdpi/ic_launcher.webp new file mode 100644 index 0000000000000000000000000000000000000000..c209e78ecd372343283f4157dcfd918ec5165bb3 Binary files /dev/null and b/android-sample/app/src/main/res/mipmap-hdpi/ic_launcher.webp differ diff --git a/android-sample/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/android-sample/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..b2dfe3d1ba5cf3ee31b3ecc1ced89044a1f3b7a9 Binary files /dev/null and b/android-sample/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp differ diff --git a/android-sample/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/android-sample/app/src/main/res/mipmap-mdpi/ic_launcher.webp new file mode 100644 index 0000000000000000000000000000000000000000..4f0f1d64e58ba64d180ce43ee13bf9a17835fbca Binary files /dev/null and b/android-sample/app/src/main/res/mipmap-mdpi/ic_launcher.webp differ diff --git a/android-sample/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/android-sample/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..62b611da081676d42f6c3f78a2c91e7bcedddedb Binary files /dev/null and b/android-sample/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp differ diff --git a/android-sample/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/android-sample/app/src/main/res/mipmap-xhdpi/ic_launcher.webp new file mode 100644 index 0000000000000000000000000000000000000000..948a3070fe34c611c42c0d3ad3013a0dce358be0 Binary files /dev/null and b/android-sample/app/src/main/res/mipmap-xhdpi/ic_launcher.webp differ diff --git a/android-sample/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/android-sample/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..1b9a6956b3acdc11f40ce2bb3f6efbd845cc243f Binary files /dev/null and b/android-sample/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp differ diff --git a/android-sample/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/android-sample/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp new file mode 100644 index 0000000000000000000000000000000000000000..28d4b77f9f036a47549d47db79c16788749dca10 Binary files /dev/null and b/android-sample/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ diff --git a/android-sample/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/android-sample/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..9287f5083623b375139afb391af71cc533a7dd37 Binary files /dev/null and b/android-sample/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp differ diff --git a/android-sample/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/android-sample/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp new file mode 100644 index 0000000000000000000000000000000000000000..aa7d6427e6fa1074b79ccd52ef67ac15c5637e85 Binary files /dev/null and b/android-sample/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ diff --git a/android-sample/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/android-sample/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp new file mode 100644 index 0000000000000000000000000000000000000000..9126ae37cbc3587421d6889eadd1d91fbf1994d4 Binary files /dev/null and b/android-sample/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp differ diff --git a/android-sample/app/src/main/res/values/strings.xml b/android-sample/app/src/main/res/values/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..a911b822ba93a6e1ae186b1231b7a5985743bc8c --- /dev/null +++ b/android-sample/app/src/main/res/values/strings.xml @@ -0,0 +1,28 @@ + + + MyID Sample + Auth + Birth date + Circle + Client ID + Dev + Ellipse + English + External id + Face + Image + Phone number + Passport or PINFL + Prod + Result image + Russian + Scan face data + Threshold + Uzbek + With photo + Without photo + Sdk hash + Manual + Resident + Non resident + diff --git a/android-sample/app/src/main/res/values/themes.xml b/android-sample/app/src/main/res/values/themes.xml new file mode 100644 index 0000000000000000000000000000000000000000..c6c20b09a38bcc485708c3a7dbede9afe99eef3c --- /dev/null +++ b/android-sample/app/src/main/res/values/themes.xml @@ -0,0 +1,4 @@ + + + + + + diff --git a/flutter-sample/android/app/src/main/res/values/strings.xml b/flutter-sample/android/app/src/main/res/values/strings.xml new file mode 100644 index 0000000000000000000000000000000000000000..73862c416f52865cd0292c70c72eb95470abb84e --- /dev/null +++ b/flutter-sample/android/app/src/main/res/values/strings.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/flutter-sample/android/app/src/main/res/values/styles.xml b/flutter-sample/android/app/src/main/res/values/styles.xml new file mode 100644 index 0000000000000000000000000000000000000000..1daf3aeeacb09e0daf01f2373aedc98f354abbec --- /dev/null +++ b/flutter-sample/android/app/src/main/res/values/styles.xml @@ -0,0 +1,11 @@ + + + + + + + diff --git a/flutter-sample/android/build.gradle b/flutter-sample/android/build.gradle new file mode 100644 index 0000000000000000000000000000000000000000..d979812819531b2e77b5c49601ee1d55414dd666 --- /dev/null +++ b/flutter-sample/android/build.gradle @@ -0,0 +1,30 @@ +buildscript { + repositories { + google() + mavenCentral() + } + + dependencies { + classpath "com.android.tools.build:gradle:7.3.1" + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.21" + } +} + +allprojects { + repositories { + google() + mavenCentral() + } +} + +rootProject.buildDir = "../build" +subprojects { + project.buildDir = "${rootProject.buildDir}/${project.name}" +} +subprojects { + project.evaluationDependsOn(":app") +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/flutter-sample/android/gradle.properties b/flutter-sample/android/gradle.properties new file mode 100644 index 0000000000000000000000000000000000000000..94adc3a3f97aa8ae37ba567d080f94f95ee8f9b7 --- /dev/null +++ b/flutter-sample/android/gradle.properties @@ -0,0 +1,3 @@ +org.gradle.jvmargs=-Xmx1536M +android.useAndroidX=true +android.enableJetifier=true diff --git a/flutter-sample/android/gradle/wrapper/gradle-wrapper.properties b/flutter-sample/android/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000000000000000000000000000000000000..16a7d6d0513ad156be3d76760c3acdd291f7cf7e --- /dev/null +++ b/flutter-sample/android/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Fri Jun 23 08:50:38 CEST 2017 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip diff --git a/flutter-sample/android/settings.gradle b/flutter-sample/android/settings.gradle new file mode 100644 index 0000000000000000000000000000000000000000..e791cf5c3cabdf398821ad858b67aef8c73075bd --- /dev/null +++ b/flutter-sample/android/settings.gradle @@ -0,0 +1,11 @@ +include ":app" + +def localPropertiesFile = new File(rootProject.projectDir, "local.properties") +def properties = new Properties() + +assert localPropertiesFile.exists() +localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } + +def flutterSdkPath = properties.getProperty("flutter.sdk") +assert flutterSdkPath != null, "flutter.sdk not set in local.properties" +apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" diff --git a/flutter-sample/lib/main.dart b/flutter-sample/lib/main.dart new file mode 100644 index 0000000000000000000000000000000000000000..b48dc4ac368ec7730a651985c03e86a21c4480e8 --- /dev/null +++ b/flutter-sample/lib/main.dart @@ -0,0 +1,68 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +void main() { + runApp(const App()); +} + +class App extends StatelessWidget { + const App({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return const MaterialApp( + title: 'AppName', + debugShowCheckedModeBanner: false, + themeMode: ThemeMode.light, + home: View(), + ); + } +} + +class View extends StatefulWidget { + const View({Key? key}) : super(key: key); + + static const platform = MethodChannel('flutter.native/myid'); + + @override + State createState() => _ViewState(); +} + +class _ViewState extends State { + var result = ""; + + @override + Widget build(BuildContext context) { + return Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + TextButton( + onPressed: () { + View.platform.invokeMethod('runSDK', { + 'KEY_PHONE_NUMBER': "1234567", // Organization phone number + 'KEY_CLIENT_ID': "", + 'KEY_PASSPORT_DATA': "AB1234567", + 'KEY_DATE_OF_BIRTH': "01.09.1999", // Format: dd.MM.yyyy + 'KEY_SDK_HASH': "", // Optional + 'KEY_EXTERNAL_ID': "", // Optional + 'KEY_THRESHOLD': 0.5, // 0.5 until 1.0 + 'KEY_BUILD_MODE': "PRODUCTION", // PRODUCTION or DEBUG + 'KEY_ENTRY_TYPE': "AUTH", // AUTH or FACE + 'KEY_RESIDENT_TYPE': "AUTH", // USER_DEFINED, RESIDENT and NON_RESIDENT + 'KEY_LOCALE': "uz", // uz, en, ru + 'KEY_CAMERA_SHAPE': "CIRCLE", // CIRCLE or ELLIPSE + 'KEY_WITH_PHOTO': false + }).then((value) => setState(() => result = value)); + }, + child: const Text("Run myID SDK"), + ), + Text( + "Result is: " + result, + style: const TextStyle(fontSize: 26), + ), + ], + ), + ); + } +} diff --git a/flutter-sample/pubspec.lock b/flutter-sample/pubspec.lock new file mode 100644 index 0000000000000000000000000000000000000000..779e035b1326e4f1732fcf713ef37af78a38a578 --- /dev/null +++ b/flutter-sample/pubspec.lock @@ -0,0 +1,167 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + async: + dependency: transitive + description: + name: async + url: "https://pub.dartlang.org" + source: hosted + version: "2.8.2" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + characters: + dependency: transitive + description: + name: characters + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" + charcode: + dependency: transitive + description: + name: charcode + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.1" + clock: + dependency: transitive + description: + name: clock + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + collection: + dependency: transitive + description: + name: collection + url: "https://pub.dartlang.org" + source: hosted + version: "1.16.0" + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.5" + fake_async: + dependency: transitive + description: + name: fake_async + url: "https://pub.dartlang.org" + source: hosted + version: "1.3.0" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.4" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + lints: + dependency: transitive + description: + name: lints + url: "https://pub.dartlang.org" + source: hosted + version: "1.0.1" + matcher: + dependency: transitive + description: + name: matcher + url: "https://pub.dartlang.org" + source: hosted + version: "0.12.11" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + url: "https://pub.dartlang.org" + source: hosted + version: "0.1.4" + meta: + dependency: transitive + description: + name: meta + url: "https://pub.dartlang.org" + source: hosted + version: "1.7.0" + path: + dependency: transitive + description: + name: path + url: "https://pub.dartlang.org" + source: hosted + version: "1.8.1" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.99" + source_span: + dependency: transitive + description: + name: source_span + url: "https://pub.dartlang.org" + source: hosted + version: "1.8.2" + stack_trace: + dependency: transitive + description: + name: stack_trace + url: "https://pub.dartlang.org" + source: hosted + version: "1.10.0" + stream_channel: + dependency: transitive + description: + name: stream_channel + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.0" + string_scanner: + dependency: transitive + description: + name: string_scanner + url: "https://pub.dartlang.org" + source: hosted + version: "1.1.0" + term_glyph: + dependency: transitive + description: + name: term_glyph + url: "https://pub.dartlang.org" + source: hosted + version: "1.2.0" + test_api: + dependency: transitive + description: + name: test_api + url: "https://pub.dartlang.org" + source: hosted + version: "0.4.9" + vector_math: + dependency: transitive + description: + name: vector_math + url: "https://pub.dartlang.org" + source: hosted + version: "2.1.2" +sdks: + dart: ">=2.17.0-0 <3.0.0" diff --git a/flutter-sample/pubspec.yaml b/flutter-sample/pubspec.yaml new file mode 100644 index 0000000000000000000000000000000000000000..6bfe5151b0c9eb79dc9ed363fbe03010732d2c6e --- /dev/null +++ b/flutter-sample/pubspec.yaml @@ -0,0 +1,89 @@ +name: example +description: A new Flutter project. + +# The following line prevents the package from being accidentally published to +# pub.dev using `flutter pub publish`. This is preferred for private packages. +publish_to: 'none' # Remove this line if you wish to publish to pub.dev + +# The following defines the version and build number for your application. +# A version number is three numbers separated by dots, like 1.2.43 +# followed by an optional build number separated by a +. +# Both the version and the builder number may be overridden in flutter +# build by specifying --build-name and --build-number, respectively. +# In Android, build-name is used as versionName while build-number used as versionCode. +# Read more about Android versioning at https://developer.android.com/studio/publish/versioning +# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion. +# Read more about iOS versioning at +# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html +version: 1.0.0+1 + +environment: + sdk: ">=2.16.2 <3.0.0" + +# Dependencies specify other packages that your package needs in order to work. +# To automatically upgrade your package dependencies to the latest versions +# consider running `flutter pub upgrade --major-versions`. Alternatively, +# dependencies can be manually updated by changing the version numbers below to +# the latest version available on pub.dev. To see which dependencies have newer +# versions available, run `flutter pub outdated`. +dependencies: + flutter: + sdk: flutter + + + # The following adds the Cupertino Icons font to your application. + # Use with the CupertinoIcons class for iOS style icons. + cupertino_icons: ^1.0.2 + +dev_dependencies: + flutter_test: + sdk: flutter + + # The "flutter_lints" package below contains a set of recommended lints to + # encourage good coding practices. The lint set provided by the package is + # activated in the `analysis_options.yaml` file located at the root of your + # package. See that file for information about deactivating specific lint + # rules and activating additional ones. + flutter_lints: ^1.0.0 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter. +flutter: + + # The following line ensures that the Material Icons font is + # included with your application, so that you can use the icons in + # the material Icons class. + uses-material-design: true + + # To add assets to your application, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/assets-and-images/#resolution-aware. + + # For details regarding adding assets from package dependencies, see + # https://flutter.dev/assets-and-images/#from-packages + + # To add custom fonts to your application, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts from package dependencies, + # see https://flutter.dev/custom-fonts/#from-packages diff --git a/images/screen01.jpg b/images/screen01.jpg new file mode 100644 index 0000000000000000000000000000000000000000..c4b04369c8c95edf791475d2d113cae664376a28 Binary files /dev/null and b/images/screen01.jpg differ diff --git a/images/screen02.jpg b/images/screen02.jpg new file mode 100644 index 0000000000000000000000000000000000000000..8c5831e5e99f63283ed709743ae979ab856830d7 Binary files /dev/null and b/images/screen02.jpg differ diff --git a/images/screen03.jpg b/images/screen03.jpg new file mode 100644 index 0000000000000000000000000000000000000000..4d1c8f78c2b5f158eb95044e4c7a63b773ee3f25 Binary files /dev/null and b/images/screen03.jpg differ diff --git a/images/screen04.jpg b/images/screen04.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ee6385ba65f4afd9d2c48d5138343226a17b63bd Binary files /dev/null and b/images/screen04.jpg differ