Skip to content

Commit f5c2b80

Browse files
committed
Use BlinkID SDK v5 for card scans.
1 parent 2a27822 commit f5c2b80

File tree

165 files changed

+1790
-7305
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

165 files changed

+1790
-7305
lines changed

.idea/misc.xml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 187 additions & 286 deletions
Large diffs are not rendered by default.

app/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/build

app/build.gradle

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
apply plugin: 'com.android.application'
2+
3+
android {
4+
compileSdkVersion 29
5+
buildToolsVersion "29.0.2"
6+
defaultConfig {
7+
applicationId "com.appliedrec.credentials.app"
8+
minSdkVersion rootProject.minSdkVersion
9+
targetSdkVersion 29
10+
versionCode rootProject.generateVersionCode()
11+
versionName rootProject.generateVersionName()
12+
buildConfigField "String", "BLINK_LICENCE_KEY", "\"" + blink5LicenceKey + "\""
13+
}
14+
buildTypes {
15+
release {
16+
minifyEnabled false
17+
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
18+
}
19+
}
20+
21+
compileOptions {
22+
sourceCompatibility JavaVersion.VERSION_1_8
23+
targetCompatibility JavaVersion.VERSION_1_8
24+
}
25+
}
26+
27+
dependencies {
28+
implementation fileTree(dir: 'libs', include: ['*.jar'])
29+
implementation "androidx.appcompat:appcompat:$rootProject.appcompatVersion"
30+
implementation "com.appliedrec.verid:rx:$rootProject.rxveridVersion"
31+
implementation "com.appliedrec.verid:ui:$rootProject.veridVersion"
32+
implementation("com.microblink:blinkid:$rootProject.blinkidVersion@aar") {
33+
transitive = true
34+
}
35+
}

app/proguard-rules.pro

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Add project specific ProGuard rules here.
2+
# You can control the set of applied configuration files using the
3+
# proguardFiles setting in build.gradle.
4+
#
5+
# For more details, see
6+
# http://developer.android.com/guide/developing/tools/proguard.html
7+
8+
# If your project uses WebView with JS, uncomment the following
9+
# and specify the fully qualified class name to the JavaScript interface
10+
# class:
11+
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12+
# public *;
13+
#}
14+
15+
# Uncomment this to preserve the line number information for
16+
# debugging stack traces.
17+
#-keepattributes SourceFile,LineNumberTable
18+
19+
# If you keep the line number information, uncomment this to
20+
# hide the original source file name.
21+
#-renamesourcefileattribute SourceFile

app/src/main/AndroidManifest.xml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
3+
xmlns:tools="http://schemas.android.com/tools"
4+
package="com.appliedrec.credentials.app"
5+
tools:ignore="GoogleAppIndexingWarning">
6+
7+
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
8+
9+
<application
10+
android:name=".CredentialsApplication"
11+
android:allowBackup="true"
12+
android:icon="@mipmap/ic_launcher"
13+
android:label="@string/app_name"
14+
android:roundIcon="@mipmap/ic_launcher_round"
15+
android:supportsRtl="true"
16+
android:theme="@style/Theme.AppCompat.Light.DarkActionBar">
17+
<activity android:name=".AboutActivity" android:label="@string/about"></activity>
18+
<activity
19+
android:name=".ScoreTableActivity"
20+
android:label="@string/score_explanation" />
21+
<activity
22+
android:name=".WebViewActivity"
23+
android:label="@string/supported_documents" />
24+
<activity
25+
android:name=".ResultActivity"
26+
android:label="@string/comparison_result" />
27+
<activity
28+
android:name=".IDCardActivity"
29+
android:label="@string/your_id_card" />
30+
<activity
31+
android:name=".MainActivity"
32+
android:label="@string/id_capture">
33+
<intent-filter>
34+
<action android:name="android.intent.action.MAIN" />
35+
36+
<category android:name="android.intent.category.LAUNCHER" />
37+
</intent-filter>
38+
</activity>
39+
40+
<meta-data
41+
android:name="com.appliedrec.verid.apiSecret"
42+
android:value="f33570cf95f874b1b260ba4def154fb23618ab89a142a726a56d70e33128181e" />
43+
</application>
44+
45+
</manifest>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package com.appliedrec.credentials.app;
2+
3+
import androidx.appcompat.app.AppCompatActivity;
4+
5+
import android.os.Bundle;
6+
7+
public class AboutActivity extends AppCompatActivity {
8+
9+
@Override
10+
protected void onCreate(Bundle savedInstanceState) {
11+
super.onCreate(savedInstanceState);
12+
setContentView(R.layout.activity_about);
13+
}
14+
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package com.appliedrec.credentials.app;
2+
3+
import android.content.Context;
4+
import android.content.SharedPreferences;
5+
import android.net.Uri;
6+
7+
import androidx.preference.PreferenceManager;
8+
9+
import com.microblink.MicroblinkSDK;
10+
import com.microblink.recognition.InvalidLicenceKeyException;
11+
12+
import java.io.BufferedReader;
13+
import java.io.InputStreamReader;
14+
import java.net.URL;
15+
16+
import javax.net.ssl.HttpsURLConnection;
17+
18+
import io.reactivex.Completable;
19+
import io.reactivex.Single;
20+
import io.reactivex.android.schedulers.AndroidSchedulers;
21+
import io.reactivex.schedulers.Schedulers;
22+
23+
class BlinkLicenceKeyUpdater {
24+
25+
private final Context context;
26+
private static final String BLINK_LICENCE_PREF_KEY = "com.appliedrec.BLINK_LICENCE_PREF_KEY";
27+
28+
BlinkLicenceKeyUpdater(Context context) {
29+
this.context = context;
30+
}
31+
32+
Single<String> getSavedLicenceKey() {
33+
return Single.<String>create(emitter -> {
34+
try {
35+
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
36+
String licenceKey = preferences.getString(BLINK_LICENCE_PREF_KEY, BuildConfig.BLINK_LICENCE_KEY);
37+
emitter.onSuccess(licenceKey);
38+
} catch (Exception e) {
39+
emitter.onError(e);
40+
}
41+
}).subscribeOn(Schedulers.io());
42+
}
43+
44+
Single<String> getLicenceKeyFromRemote() {
45+
return Single.<String>create(emitter -> {
46+
try {
47+
String packageName = context.getApplicationContext().getPackageName();
48+
String uri = new Uri.Builder()
49+
.scheme("https")
50+
.authority("dev.ver-id.com")
51+
.path("blink_key")
52+
.appendQueryParameter("package", packageName)
53+
.build().toString();
54+
URL url = new URL(uri);
55+
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
56+
connection.setUseCaches(false);
57+
connection.setRequestMethod("GET");
58+
connection.setRequestProperty("Accept", "text/plain");
59+
connection.setConnectTimeout(30000);
60+
connection.setReadTimeout(30000);
61+
int status = connection.getResponseCode();
62+
if (status == HttpsURLConnection.HTTP_OK) {
63+
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()));
64+
String line = reader.readLine();
65+
reader.close();
66+
if (line != null) {
67+
emitter.onSuccess(line);
68+
} else {
69+
throw new Exception("Unable to read response");
70+
}
71+
} else {
72+
throw new Exception("Received http status " + status);
73+
}
74+
} catch (Exception e) {
75+
emitter.onError(e);
76+
}
77+
}).subscribeOn(Schedulers.io());
78+
}
79+
80+
Completable setLicenceKey(String licenceKey) {
81+
return Completable.create(emitter -> {
82+
try {
83+
MicroblinkSDK.setLicenseKey(licenceKey, context);
84+
SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
85+
preferences.edit().putString(BLINK_LICENCE_PREF_KEY, licenceKey).apply();
86+
emitter.onComplete();
87+
} catch (InvalidLicenceKeyException e) {
88+
emitter.onError(e);
89+
}
90+
}).subscribeOn(AndroidSchedulers.mainThread());
91+
}
92+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.appliedrec.credentials.app;
2+
3+
import android.app.Application;
4+
5+
import com.appliedrec.rxverid.RxVerID;
6+
import com.microblink.MicroblinkSDK;
7+
import com.microblink.intent.IntentDataTransferMode;
8+
9+
public class CredentialsApplication extends Application {
10+
11+
private RxVerID rxVerID;
12+
13+
@Override
14+
public void onCreate() {
15+
super.onCreate();
16+
setupMicroblink();
17+
setupVerID();
18+
}
19+
20+
private void setupMicroblink() {
21+
MicroblinkSDK.setIntentDataTransferMode(IntentDataTransferMode.PERSISTED_OPTIMISED);
22+
MicroblinkSDK.setShowTimeLimitedLicenseWarning(false);
23+
}
24+
25+
private void setupVerID() {
26+
rxVerID = new RxVerID.Builder(this).build();
27+
}
28+
29+
public RxVerID getRxVerID() {
30+
return rxVerID;
31+
}
32+
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
package com.appliedrec.credentials.app;
2+
3+
import android.content.Context;
4+
import android.content.res.TypedArray;
5+
import android.graphics.Canvas;
6+
import android.graphics.Color;
7+
import android.graphics.Paint;
8+
import android.graphics.Path;
9+
import android.graphics.PointF;
10+
import android.util.AttributeSet;
11+
import android.view.View;
12+
13+
import androidx.annotation.MainThread;
14+
15+
public class DialView extends View {
16+
17+
private int needleColor = Color.BLACK;
18+
private float needleWidth = 3f;
19+
private float ovalThickness = 30f;
20+
private final Path failPath = new Path();
21+
private final Path passPath = new Path();
22+
private final Path needlePath = new Path();
23+
private float failAngle = 90f;
24+
private float passAngle = 90f;
25+
private final Paint failPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
26+
private final Paint passPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
27+
private final Paint needlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
28+
private final Paint needleCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
29+
private final PointF needleEnd = new PointF();
30+
private float needleCircleWidth = 8f;
31+
private double scoreAngle = 0;
32+
33+
public DialView(Context context) {
34+
super(context);
35+
init(null, 0);
36+
}
37+
38+
public DialView(Context context, AttributeSet attrs) {
39+
super(context, attrs);
40+
init(attrs, 0);
41+
}
42+
43+
public DialView(Context context, AttributeSet attrs, int defStyle) {
44+
super(context, attrs, defStyle);
45+
init(attrs, defStyle);
46+
}
47+
48+
private void init(AttributeSet attrs, int defStyle) {
49+
// Load attributes
50+
final TypedArray a = getContext().obtainStyledAttributes(
51+
attrs, R.styleable.DialView, defStyle, 0);
52+
53+
needleColor = a.getColor(R.styleable.DialView_needleColor, needleColor);
54+
55+
float density = getResources().getDisplayMetrics().density;
56+
needleWidth = a.getDimension(R.styleable.DialView_needleWidth, needleWidth * density);
57+
58+
ovalThickness = a.getDimension(R.styleable.DialView_ovalThickness, ovalThickness * density);
59+
60+
a.recycle();
61+
62+
needleCircleWidth = needleWidth * 3;
63+
64+
failPaint.setColor(Color.RED);
65+
failPaint.setStyle(Paint.Style.STROKE);
66+
failPaint.setStrokeCap(Paint.Cap.BUTT);
67+
failPaint.setStrokeWidth(ovalThickness);
68+
69+
passPaint.setColor(Color.GREEN);
70+
passPaint.setStyle(Paint.Style.STROKE);
71+
passPaint.setStrokeCap(Paint.Cap.BUTT);
72+
passPaint.setStrokeWidth(ovalThickness);
73+
74+
needleCirclePaint.setColor(needleColor);
75+
needleCirclePaint.setStyle(Paint.Style.FILL);
76+
77+
needlePaint.setColor(needleColor);
78+
needlePaint.setStyle(Paint.Style.STROKE);
79+
needlePaint.setStrokeCap(Paint.Cap.ROUND);
80+
needlePaint.setStrokeWidth(needleWidth);
81+
}
82+
83+
@MainThread
84+
public void setScore(float score, float threshold, float max) {
85+
failAngle = threshold/max * 180;
86+
passAngle = 180 - failAngle;
87+
scoreAngle = score / max * Math.PI;
88+
invalidate();
89+
}
90+
91+
@Override
92+
protected void onDraw(Canvas canvas) {
93+
super.onDraw(canvas);
94+
95+
needleEnd.x = (float)(getWidth()/2f - Math.cos(scoreAngle) * getWidth()/2f);
96+
needleEnd.y = (float)(getHeight() - Math.sin(scoreAngle) * getHeight());
97+
98+
failPath.reset();
99+
failPath.addArc(ovalThickness/2f, ovalThickness/2f, getWidth()-ovalThickness/2f, getHeight()*2-ovalThickness/2f, 180f, failAngle);
100+
canvas.drawPath(failPath, failPaint);
101+
102+
passPath.reset();
103+
passPath.addArc(ovalThickness/2f, ovalThickness/2f, getWidth()-ovalThickness/2f, getHeight()*2-ovalThickness/2f, 180f+failAngle, passAngle);
104+
canvas.drawPath(passPath, passPaint);
105+
106+
needlePath.reset();
107+
needlePath.moveTo(getWidth()/2f, getHeight());
108+
needlePath.lineTo(needleEnd.x, needleEnd.y);
109+
canvas.drawPath(needlePath, needlePaint);
110+
111+
canvas.drawOval(getWidth()/2f-needleCircleWidth/2f, getHeight()-needleCircleWidth/2f, getWidth()/2f+needleCircleWidth/2f, getHeight()+needleCircleWidth/2f, needleCirclePaint);
112+
}
113+
}

0 commit comments

Comments
 (0)