diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..d4c3a57
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,16 @@
+*.iml
+.gradle
+/local.properties
+/.idea/caches
+/.idea/libraries
+/.idea/modules.xml
+/.idea/workspace.xml
+/.idea/navEditor.xml
+/.idea/assetWizardSettings.xml
+.DS_Store
+/build
+/captures
+.externalNativeBuild
+.cxx
+local.properties
+/.idea/
diff --git a/app/.gitignore b/app/.gitignore
new file mode 100644
index 0000000..42afabf
--- /dev/null
+++ b/app/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/app/build.gradle b/app/build.gradle
new file mode 100644
index 0000000..9623f2c
--- /dev/null
+++ b/app/build.gradle
@@ -0,0 +1,56 @@
+plugins {
+ id 'com.android.application'
+ id 'org.jetbrains.kotlin.android'
+}
+
+android {
+ namespace 'com.kbyai.idcardrecognition'
+ compileSdk 34
+
+ defaultConfig {
+ applicationId "com.kbyai.idcardrecognition"
+ minSdk 24
+ targetSdk 34
+ versionCode 5
+ versionName "1.4"
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+
+ ndk {
+ abiFilters 'arm64-v8a', 'armeabi-v7a'
+ }
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
+}
+
+dependencies {
+
+ implementation 'androidx.core:core-ktx:1.7.0'
+ implementation 'androidx.appcompat:appcompat:1.6.1'
+ implementation 'com.google.android.material:material:1.9.0'
+ implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
+
+ implementation project(path: ':libidsdk')
+
+ implementation 'com.itextpdf:itextpdf:5.5.10'
+
+ // PDF library
+ implementation 'io.fotoapparat:fotoapparat:2.7.0'
+
+ testImplementation 'junit:junit:4.13.2'
+ androidTestImplementation 'androidx.test.ext:junit:1.1.5'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
+}
\ No newline at end of file
diff --git a/app/idcard.jks b/app/idcard.jks
new file mode 100644
index 0000000..acdc3c1
Binary files /dev/null and b/app/idcard.jks differ
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
new file mode 100644
index 0000000..481bb43
--- /dev/null
+++ b/app/proguard-rules.pro
@@ -0,0 +1,21 @@
+# 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
diff --git a/app/src/androidTest/java/com/kbyai/idcardrecognition/ExampleInstrumentedTest.kt b/app/src/androidTest/java/com/kbyai/idcardrecognition/ExampleInstrumentedTest.kt
new file mode 100644
index 0000000..a729d63
--- /dev/null
+++ b/app/src/androidTest/java/com/kbyai/idcardrecognition/ExampleInstrumentedTest.kt
@@ -0,0 +1,24 @@
+package com.kbyai.idcardrecognition
+
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.ext.junit.runners.AndroidJUnit4
+
+import org.junit.Test
+import org.junit.runner.RunWith
+
+import org.junit.Assert.*
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+@RunWith(AndroidJUnit4::class)
+class ExampleInstrumentedTest {
+ @Test
+ fun useAppContext() {
+ // Context of the app under test.
+ val appContext = InstrumentationRegistry.getInstrumentation().targetContext
+ assertEquals("com.kbyai.idcardrecognition", appContext.packageName)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..af42416
--- /dev/null
+++ b/app/src/main/AndroidManifest.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/kbyai/idcardrecognition/AboutActivity.kt b/app/src/main/java/com/kbyai/idcardrecognition/AboutActivity.kt
new file mode 100644
index 0000000..1453be0
--- /dev/null
+++ b/app/src/main/java/com/kbyai/idcardrecognition/AboutActivity.kt
@@ -0,0 +1,150 @@
+package com.kbyai.idcardrecognition
+
+import android.content.Intent
+import android.content.pm.ResolveInfo
+import android.net.Uri
+import android.os.Bundle
+import android.widget.TextView
+import androidx.appcompat.app.AppCompatActivity
+import com.kbyai.idcardrecognition.R
+
+
+class AboutActivity : AppCompatActivity() {
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_about)
+
+ findViewById(R.id.txtMail).setOnClickListener {
+ val intent = Intent(Intent.ACTION_SEND)
+ intent.type = "plain/text"
+ intent.putExtra(Intent.EXTRA_EMAIL, arrayOf("contact@kby-ai.com"))
+ intent.putExtra(Intent.EXTRA_SUBJECT, "License Request")
+ intent.putExtra(Intent.EXTRA_TEXT, "")
+ startActivity(Intent.createChooser(intent, ""))
+ }
+
+ findViewById(R.id.txtWhatsapp).setOnClickListener {
+ val general = Intent(Intent.ACTION_VIEW, Uri.parse("https://com.whatsapp/kbyai"))
+ val generalResolvers: HashSet = HashSet()
+ val generalResolveInfo: List = packageManager.queryIntentActivities(general, 0)
+ for (info in generalResolveInfo) {
+ if (info.activityInfo.packageName != null) {
+ generalResolvers.add(info.activityInfo.packageName)
+ }
+ }
+
+ val telegram = Intent(Intent.ACTION_VIEW, Uri.parse("https://wa.me/19092802609"))
+ var goodResolver = 0
+
+ val resInfo: List = packageManager.queryIntentActivities(telegram, 0)
+ if (!resInfo.isEmpty()) {
+ for (info in resInfo) {
+ if (info.activityInfo.packageName != null && !generalResolvers.contains(info.activityInfo.packageName)) {
+ goodResolver++
+ telegram.setPackage(info.activityInfo.packageName)
+ }
+ }
+ }
+
+ if (goodResolver != 1) {
+ telegram.setPackage(null)
+ }
+ if (telegram.resolveActivity(packageManager) != null) {
+ startActivity(telegram)
+ }
+ }
+
+ findViewById(R.id.txtTelegram).setOnClickListener {
+ val general = Intent(Intent.ACTION_VIEW, Uri.parse("https://t.com/kbyai"))
+ val generalResolvers: HashSet = HashSet()
+ val generalResolveInfo: List = packageManager.queryIntentActivities(general, 0)
+ for (info in generalResolveInfo) {
+ if (info.activityInfo.packageName != null) {
+ generalResolvers.add(info.activityInfo.packageName)
+ }
+ }
+
+ val telegram = Intent(Intent.ACTION_VIEW, Uri.parse("https://t.me/kbyai"))
+ var goodResolver = 0
+
+ val resInfo: List = packageManager.queryIntentActivities(telegram, 0)
+ if (!resInfo.isEmpty()) {
+ for (info in resInfo) {
+ if (info.activityInfo.packageName != null && !generalResolvers.contains(info.activityInfo.packageName)) {
+ goodResolver++
+ telegram.setPackage(info.activityInfo.packageName)
+ }
+ }
+ }
+
+ if (goodResolver != 1) {
+ telegram.setPackage(null)
+ }
+ if (telegram.resolveActivity(packageManager) != null) {
+ startActivity(telegram)
+ }
+ }
+
+ findViewById(R.id.txtSkype).setOnClickListener {
+ val general = Intent(Intent.ACTION_VIEW, Uri.parse("https://com.skype/kbyai"))
+ val generalResolvers: HashSet = HashSet()
+ val generalResolveInfo: List = packageManager.queryIntentActivities(general, 0)
+ for (info in generalResolveInfo) {
+ if (info.activityInfo.packageName != null) {
+ generalResolvers.add(info.activityInfo.packageName)
+ }
+ }
+
+ val telegram = Intent(Intent.ACTION_VIEW, Uri.parse("https://join.skype.com/invite/OffY2r1NUFev"))
+ var goodResolver = 0
+
+ val resInfo: List = packageManager.queryIntentActivities(telegram, 0)
+ if (!resInfo.isEmpty()) {
+ for (info in resInfo) {
+ if (info.activityInfo.packageName != null && !generalResolvers.contains(info.activityInfo.packageName)) {
+ goodResolver++
+ telegram.setPackage(info.activityInfo.packageName)
+ }
+ }
+ }
+
+ if (goodResolver != 1) {
+ telegram.setPackage(null)
+ }
+ if (telegram.resolveActivity(packageManager) != null) {
+ startActivity(telegram)
+ }
+ }
+
+ findViewById(R.id.txtGitHub).setOnClickListener {
+ val general = Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/kby-ai"))
+ val generalResolvers: HashSet = HashSet()
+ val generalResolveInfo: List = packageManager.queryIntentActivities(general, 0)
+ for (info in generalResolveInfo) {
+ if (info.activityInfo.packageName != null) {
+ generalResolvers.add(info.activityInfo.packageName)
+ }
+ }
+
+ val telegram = Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/kby-ai"))
+ var goodResolver = 0
+
+ val resInfo: List = packageManager.queryIntentActivities(telegram, 0)
+ if (!resInfo.isEmpty()) {
+ for (info in resInfo) {
+ if (info.activityInfo.packageName != null && !generalResolvers.contains(info.activityInfo.packageName)) {
+ goodResolver++
+ telegram.setPackage(info.activityInfo.packageName)
+ }
+ }
+ }
+
+ if (goodResolver != 1) {
+ telegram.setPackage(null)
+ }
+ if (telegram.resolveActivity(packageManager) != null) {
+ startActivity(telegram)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/kbyai/idcardrecognition/CameraActivityKt.kt b/app/src/main/java/com/kbyai/idcardrecognition/CameraActivityKt.kt
new file mode 100644
index 0000000..51496bb
--- /dev/null
+++ b/app/src/main/java/com/kbyai/idcardrecognition/CameraActivityKt.kt
@@ -0,0 +1,141 @@
+package com.kbyai.idcardrecognition;
+
+import android.Manifest
+import android.content.Context
+import android.content.Intent
+import android.content.pm.PackageManager
+import android.graphics.Rect
+import android.os.Bundle
+import android.util.Log
+import android.util.Size
+import androidx.appcompat.app.AppCompatActivity
+import androidx.core.app.ActivityCompat
+import androidx.core.content.ContextCompat
+import com.kbyai.idsdk.IDSDK
+import io.fotoapparat.Fotoapparat
+import io.fotoapparat.parameter.Resolution
+import io.fotoapparat.preview.Frame
+import io.fotoapparat.preview.FrameProcessor
+import io.fotoapparat.selector.back
+import io.fotoapparat.view.CameraView
+import org.json.JSONObject
+
+class CameraActivityKt : AppCompatActivity() {
+
+ val TAG = CameraActivityKt::class.java.simpleName
+ val PREVIEW_WIDTH = 720
+ val PREVIEW_HEIGHT = 1280
+
+ private lateinit var cameraView: CameraView
+ private lateinit var faceView: FaceView
+ private lateinit var fotoapparat: Fotoapparat
+ private lateinit var context: Context
+ private var documenName: String = ""
+ private var positionRect: Rect = Rect()
+
+ private var recognized = false
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_camera_kt)
+
+ context = this
+ cameraView = findViewById(R.id.preview)
+ faceView = findViewById(R.id.faceView)
+
+ fotoapparat = Fotoapparat.with(this)
+ .into(cameraView)
+ .lensPosition(back())
+ .frameProcessor(FaceFrameProcessor())
+ .previewResolution { Resolution(PREVIEW_HEIGHT,PREVIEW_WIDTH) }
+ .build()
+
+ if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
+ == PackageManager.PERMISSION_DENIED
+ ) {
+ ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA), 1)
+ } else {
+ fotoapparat.start()
+ }
+ }
+
+ override fun onResume() {
+ super.onResume()
+ recognized = false
+ if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
+ == PackageManager.PERMISSION_GRANTED
+ ) {
+ fotoapparat.start()
+ }
+ }
+
+ override fun onPause() {
+ super.onPause()
+ fotoapparat.stop()
+ faceView.setDocumentInfos(null, "")
+ }
+
+ override fun onRequestPermissionsResult(
+ requestCode: Int,
+ permissions: Array,
+ grantResults: IntArray
+ ) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults)
+ if (requestCode == 1) {
+ if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA)
+ == PackageManager.PERMISSION_GRANTED
+ ) {
+ fotoapparat.start()
+ }
+ }
+ }
+
+ inner class FaceFrameProcessor : FrameProcessor {
+
+ override fun process(frame: Frame) {
+
+ if(recognized == true) {
+ return
+ }
+
+ val bitmap = IDSDK.yuv2Bitmap(frame.image, frame.size.width, frame.size.height, 6)
+ val result = IDSDK.idcardRecognition(bitmap)
+
+ try {
+ val jsonResult = JSONObject(result)
+ val positionObj = jsonResult["Position"] as JSONObject
+ val hasMrz = jsonResult.has("MRZ")
+ documenName = jsonResult["Document Name"] as String
+ val quality = jsonResult["Quality"] as Int
+ val x1 = positionObj["x1"] as Int
+ val y1 = positionObj["y1"] as Int
+ val x2 = positionObj["x2"] as Int
+ val y2 = positionObj["y2"] as Int
+ positionRect = Rect(x1, y1, x2, y2)
+ if (quality > 86 && (documenName != "Unknown" || hasMrz == true)) {
+ recognized = true
+
+ runOnUiThread {
+ faceView.setFrameSize(Size(bitmap.width, bitmap.height))
+ faceView.setDocumentInfos(positionRect, documenName)
+ }
+
+ runOnUiThread {
+ ResultActivity.resultString = jsonResult.toString()
+ val intent = Intent(context, ResultActivity::class.java)
+ startActivity(intent)
+ }
+ }
+ documenName = documenName + " " + quality
+ } catch (e1: Exception) {
+ documenName = ""
+ positionRect = Rect()
+ }
+
+ runOnUiThread {
+ faceView.setFrameSize(Size(bitmap.width, bitmap.height))
+ faceView.setDocumentInfos(positionRect, documenName)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/kbyai/idcardrecognition/FaceView.java b/app/src/main/java/com/kbyai/idcardrecognition/FaceView.java
new file mode 100644
index 0000000..77d1616
--- /dev/null
+++ b/app/src/main/java/com/kbyai/idcardrecognition/FaceView.java
@@ -0,0 +1,92 @@
+package com.kbyai.idcardrecognition;
+
+import android.content.Context;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.Size;
+import android.view.View;
+
+import androidx.annotation.Nullable;
+
+import java.util.List;
+
+public class FaceView extends View {
+
+ private Context context;
+ private Paint realPaint;
+ private Paint spoofPaint;
+
+ private Size frameSize;
+
+ private Rect position;
+
+ private String documentName;
+
+ public FaceView(Context context) {
+ this(context, null);
+
+ this.context = context;
+ init();
+ }
+
+ public FaceView(Context context, @Nullable AttributeSet attrs) {
+ super(context, attrs);
+ this.context = context;
+
+ init();
+ }
+
+ public void init() {
+ setLayerType(View.LAYER_TYPE_SOFTWARE, null);
+
+ realPaint = new Paint();
+ realPaint.setStyle(Paint.Style.STROKE);
+ realPaint.setStrokeWidth(3);
+ realPaint.setColor(Color.GREEN);
+ realPaint.setAntiAlias(true);
+ realPaint.setTextSize(50);
+
+ spoofPaint = new Paint();
+ spoofPaint.setStyle(Paint.Style.STROKE);
+ spoofPaint.setStrokeWidth(3);
+ spoofPaint.setColor(Color.RED);
+ spoofPaint.setAntiAlias(true);
+ spoofPaint.setTextSize(50);
+ }
+
+ public void setFrameSize(Size frameSize)
+ {
+ this.frameSize = frameSize;
+ }
+
+ public void setDocumentInfos(Rect position, String documentName)
+ {
+ this.position = position;
+ this.documentName = documentName;
+ invalidate();
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ super.onDraw(canvas);
+
+ if(position != null && !position.isEmpty()) {
+ float x_scale = this.frameSize.getWidth() / (float)canvas.getWidth();
+ float y_scale = this.frameSize.getHeight() / (float)canvas.getHeight();
+
+ realPaint.setStrokeWidth(3);
+ realPaint.setStyle(Paint.Style.FILL_AND_STROKE);
+ canvas.drawText(documentName, (position.left / x_scale) + 10, (position.top / y_scale) - 30, realPaint);
+
+ realPaint.setStyle(Paint.Style.STROKE);
+ realPaint.setStrokeWidth(5);
+
+ canvas.drawRect(new Rect((int)(position.left / x_scale), (int)(position.top / y_scale),
+ (int)(position.right / x_scale), (int)(position.bottom / y_scale)), realPaint);
+ }
+ }
+}
diff --git a/app/src/main/java/com/kbyai/idcardrecognition/MainActivity.kt b/app/src/main/java/com/kbyai/idcardrecognition/MainActivity.kt
new file mode 100644
index 0000000..7021b1f
--- /dev/null
+++ b/app/src/main/java/com/kbyai/idcardrecognition/MainActivity.kt
@@ -0,0 +1,76 @@
+package com.kbyai.idcardrecognition
+
+import android.content.Intent
+import android.graphics.Bitmap
+import android.os.Bundle
+import android.util.Log
+import android.widget.Button
+import android.widget.TextView
+import androidx.appcompat.app.AppCompatActivity
+import com.kbyai.idsdk.IDSDK
+import org.json.JSONObject
+import android.widget.Toast
+
+class MainActivity : AppCompatActivity() {
+ companion object {
+ private val SELECT_PHOTO_REQUEST_CODE = 1
+ private val IDCARD_RECOGNITION_REQUEST_CODE = 2
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_main)
+
+ var ret = IDSDK.setActivation(
+ "ItbU8EMHg1dFLQgkk7h4IP+Zu/CkrfVWGEEmOY5IjiAmxvcEU1fqJ3C76+CoZ2zit816tchptZDn\n" +
+ "61TCAtHBKVV6Fub3tmoyHl8kJz4pOMX4OQ2qUEhyvI2WzRN8/FUZ6ZAdUGw/4I3SJfTxdxD55MJ3\n" +
+ "/rOt5C8OLJvR8sBTx+ltt9J2hGMO+T5Jf1ndrj00djN6/v5PtcQqFJiDQTbVdFyCm6E4w66Mgx63\n" +
+ "FWtYRgBd1qC3f9FFeFvICppd2BvEsuaw2n/8/6qDj6X1kTdYgYRtRD5VKPTnmAV04sV90EA/3Hm5\n" +
+ "xLeVxrn4C9SiQJ5t9T1g0EX0pOrY7SPlfLUocg=="
+ )
+ if(ret == IDSDK.SDK_SUCCESS) {
+ ret = IDSDK.init(this)
+ }
+
+ findViewById