Skip to content
This repository was archived by the owner on Sep 13, 2024. It is now read-only.

Commit fafeb0e

Browse files
Merge pull request #28 from coderbunker/issue#27-eye_tracking
Issue#27 eye tracking
2 parents 55f1d1c + 5063fae commit fafeb0e

7 files changed

Lines changed: 254 additions & 8 deletions

File tree

0 Bytes
Binary file not shown.

app/src/main/AndroidManifest.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<!-- Give permission to use Internet -->
66
<uses-permission android:name="android.permission.INTERNET" />
77
<uses-permission android:name="android.permission.REORDER_TASKS" />
8-
8+
<uses-permission android:name="android.permission.CAMERA" />
99

1010
<application
1111
android:allowBackup="false"

app/src/main/java/com/coderbunker/kioskapp/KioskActivity.java

Lines changed: 96 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
import android.content.Intent;
88
import android.content.SharedPreferences;
99
import android.content.pm.ActivityInfo;
10+
import android.content.pm.PackageManager;
11+
import android.hardware.Camera;
1012
import android.net.http.SslError;
1113
import android.os.Bundle;
1214
import android.view.KeyEvent;
@@ -15,25 +17,33 @@
1517
import android.view.Window;
1618
import android.view.WindowManager;
1719
import android.webkit.SslErrorHandler;
20+
import android.webkit.WebSettings;
1821
import android.webkit.WebView;
1922
import android.webkit.WebViewClient;
2023
import android.widget.Button;
24+
import android.widget.FrameLayout;
25+
import android.widget.TextView;
2126
import android.widget.Toast;
2227

28+
import com.coderbunker.kioskapp.facerecognition.CameraPreview;
29+
import com.coderbunker.kioskapp.facerecognition.FaceDetectionListener;
2330
import com.coderbunker.kioskapp.lib.HOTP;
2431
import com.coderbunker.kioskapp.lib.TOTP;
2532

2633
import java.util.ArrayList;
2734
import java.util.Arrays;
2835
import java.util.List;
36+
import java.util.Observable;
37+
import java.util.Observer;
2938
import java.util.Timer;
3039
import java.util.TimerTask;
3140

3241

33-
public class KioskActivity extends Activity {
42+
public class KioskActivity extends Activity implements Observer {
3443

3544
private final Context context = this;
3645
private WebView webView;
46+
private TextView face_detection_score, face_counter_view;
3747
private static String password = "1234";
3848
private static String URL = "";
3949

@@ -55,6 +65,9 @@ public class KioskActivity extends Activity {
5565

5666
private SharedPreferences prefs;
5767

68+
private Camera mCamera;
69+
private CameraPreview mCameraPreview;
70+
5871
@Override
5972
public void onBackPressed() {
6073
//Do nothing...
@@ -80,7 +93,7 @@ protected void onCreate(Bundle savedInstanceState) {
8093
prefs = this.getSharedPreferences(
8194
"com.coderbunker.kioskapp", Context.MODE_PRIVATE);
8295

83-
URL = prefs.getString("url", "https://naibaben.github.io/");
96+
URL = prefs.getString("url", "https://coderbunker.github.io/kiosk-web/");
8497
String otp = prefs.getString("otp", null);
8598

8699
if (otp == null) {
@@ -92,6 +105,8 @@ protected void onCreate(Bundle savedInstanceState) {
92105

93106
//Get the webView and load the URL
94107
webView = findViewById(R.id.webview);
108+
face_detection_score = findViewById(R.id.face_detection_score);
109+
face_counter_view = findViewById(R.id.face_counter);
95110
webView.setWebViewClient(new WebViewClient() {
96111
@Override
97112
public void onPageFinished(final WebView view, String url) {
@@ -127,6 +142,10 @@ public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError e
127142
}
128143
});
129144
webView.getSettings().setJavaScriptEnabled(true);
145+
webView.getSettings().setAppCacheEnabled(true);
146+
webView.getSettings().setAppCacheMaxSize(5000 * 1000 * 1000);
147+
webView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);
148+
webView.getSettings().setMediaPlaybackRequiresUserGesture(false);
130149
webView.loadUrl(URL);
131150

132151
Toast.makeText(this, "Loading " + URL, Toast.LENGTH_SHORT).show();
@@ -185,6 +204,28 @@ public void run() {
185204
});
186205

187206
numbers = new ArrayList<>();
207+
208+
209+
if (checkCameraHardware(this)) {
210+
mCamera = getCameraInstance();
211+
if (mCamera != null) {
212+
213+
FaceDetectionListener faceDetectionListener = new FaceDetectionListener();
214+
faceDetectionListener.addObserver(this);
215+
mCamera.setFaceDetectionListener(faceDetectionListener);
216+
217+
mCameraPreview = new CameraPreview(this, mCamera);
218+
219+
FrameLayout preview = findViewById(R.id.camera_preview);
220+
preview.addView(mCameraPreview);
221+
222+
mCamera.startPreview();
223+
} else {
224+
225+
}
226+
}
227+
228+
188229
}
189230

190231

@@ -398,4 +439,57 @@ public void onClick(View v) {
398439
dialog.show();
399440
}
400441

442+
public static Camera getCameraInstance() {
443+
Camera c = null;
444+
try {
445+
c = Camera.open(Camera.CameraInfo.CAMERA_FACING_FRONT); // attempt to get a Camera instance
446+
} catch (Exception e) {
447+
// Camera is not available (in use or does not exist)
448+
e.printStackTrace();
449+
}
450+
return c; // returns null if camera is unavailable
451+
}
452+
453+
private boolean checkCameraHardware(Context context) {
454+
if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
455+
// this device has a camera
456+
return true;
457+
} else {
458+
// no camera on this device
459+
return false;
460+
}
461+
}
462+
463+
@Override
464+
protected void onPause() {
465+
super.onPause();
466+
}
467+
468+
private long last_detected = 0;
469+
private long face_current_counter = 0;
470+
private long face_counter = 0;
471+
472+
@Override
473+
public void update(Observable o, Object arg) {
474+
if (o instanceof FaceDetectionListener) {
475+
Camera.Face face = ((Camera.Face) arg);
476+
477+
face_detection_score.setText("Score:" + face.score);
478+
479+
if (face.score >= 85) {
480+
face_current_counter++;
481+
} else {
482+
face_current_counter = 0;
483+
}
484+
485+
if (face_current_counter >= 5 && last_detected < System.currentTimeMillis() + 45000) {
486+
face_counter++;
487+
last_detected = System.currentTimeMillis();
488+
face_current_counter = -5000;
489+
}
490+
491+
face_counter_view.setText("Viewers: " + face_counter);
492+
493+
}
494+
}
401495
}

app/src/main/java/com/coderbunker/kioskapp/SettingsActivity.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ public void onClick(View v) {
7171
});
7272

7373
String otp = prefs.getString("otp", null);
74-
String url = prefs.getString("url", "https://naibaben.github.io/");
74+
String url = prefs.getString("url", "https://coderbunker.github.io/kiosk-web/");
7575
int hotp_counter = prefs.getInt("hotp_counter", 0);
7676

7777
editURL.setText(url);
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
package com.coderbunker.kioskapp.facerecognition;
2+
3+
import android.content.Context;
4+
import android.hardware.Camera;
5+
import android.util.Log;
6+
import android.view.SurfaceHolder;
7+
import android.view.SurfaceView;
8+
9+
import java.io.IOException;
10+
11+
import static android.content.ContentValues.TAG;
12+
13+
/**
14+
* A basic Camera preview class
15+
*/
16+
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
17+
private SurfaceHolder mHolder;
18+
private Camera mCamera;
19+
20+
public CameraPreview(Context context, Camera camera) {
21+
super(context);
22+
mCamera = camera;
23+
24+
// Install a SurfaceHolder.Callback so we get notified when the
25+
// underlying surface is created and destroyed.
26+
mHolder = getHolder();
27+
mHolder.addCallback(this);
28+
// deprecated setting, but required on Android versions prior to 3.0
29+
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
30+
}
31+
32+
public void surfaceCreated(SurfaceHolder holder) {
33+
try {
34+
mCamera.setPreviewDisplay(holder);
35+
mCamera.startPreview();
36+
37+
startFaceDetection(); // start face detection feature
38+
39+
} catch (IOException e) {
40+
Log.d(TAG, "Error setting camera preview: " + e.getMessage());
41+
}
42+
}
43+
44+
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
45+
46+
if (holder.getSurface() == null) {
47+
// preview surface does not exist
48+
Log.d(TAG, "holder.getSurface() == null");
49+
return;
50+
}
51+
52+
try {
53+
mCamera.stopPreview();
54+
55+
} catch (Exception e) {
56+
// ignore: tried to stop a non-existent preview
57+
Log.d(TAG, "Error stopping camera preview: " + e.getMessage());
58+
}
59+
60+
try {
61+
mCamera.setPreviewDisplay(holder);
62+
mCamera.startPreview();
63+
64+
startFaceDetection(); // re-start face detection feature
65+
66+
} catch (Exception e) {
67+
// ignore: tried to stop a non-existent preview
68+
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
69+
}
70+
}
71+
72+
public void surfaceDestroyed(SurfaceHolder holder) {
73+
// empty. Take care of releasing the Camera preview in your activity.
74+
}
75+
76+
public void startFaceDetection() {
77+
// Try starting Face Detection
78+
Camera.Parameters params = mCamera.getParameters();
79+
80+
// start face detection only *after* preview has started
81+
if (params.getMaxNumDetectedFaces() > 0) {
82+
// camera supports face detection, so can start it:
83+
mCamera.startFaceDetection();
84+
}
85+
}
86+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.coderbunker.kioskapp.facerecognition;
2+
3+
import android.hardware.Camera;
4+
5+
import java.util.Observable;
6+
7+
public class FaceDetectionListener extends Observable implements Camera.FaceDetectionListener {
8+
9+
@Override
10+
public void onFaceDetection(Camera.Face[] faces, Camera camera) {
11+
if (faces.length > 0) {
12+
for (Camera.Face face : faces) {
13+
try {
14+
/*System.out.println("--------------------------");
15+
System.out.println(face.score);*/
16+
setChanged();
17+
notifyObservers(face);
18+
} catch (Exception e) {
19+
e.printStackTrace();
20+
}
21+
}
22+
}
23+
}
24+
}
Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,53 @@
11
<?xml version="1.0" encoding="utf-8"?>
22

3+
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
4+
xmlns:tools="http://schemas.android.com/tools"
5+
android:layout_width="match_parent"
6+
android:layout_height="match_parent">
37

4-
<WebView android:id="@+id/webview"
5-
android:layout_width="fill_parent"
6-
android:layout_height="fill_parent"
7-
xmlns:android="http://schemas.android.com/apk/res/android">
8+
<WebView
9+
android:id="@+id/webview"
10+
android:layout_width="fill_parent"
11+
android:layout_height="fill_parent">
812

913
</WebView>
1014

1115

16+
<FrameLayout
17+
android:id="@+id/camera_preview"
18+
android:layout_width="1dp"
19+
android:layout_height="1dp"
20+
android:visibility="visible">
21+
22+
</FrameLayout>
23+
24+
<TextView
25+
android:id="@+id/face_detection_score"
26+
android:layout_width="wrap_content"
27+
android:layout_height="wrap_content"
28+
android:layout_alignParentBottom="true"
29+
android:layout_alignParentEnd="true"
30+
android:layout_marginBottom="21dp"
31+
android:layout_marginEnd="30dp"
32+
android:text="TextView"
33+
android:visibility="gone"
34+
tools:layout_editor_absoluteX="758dp"
35+
tools:layout_editor_absoluteY="1123dp" />
36+
37+
<TextView
38+
android:id="@+id/face_counter"
39+
android:layout_width="wrap_content"
40+
android:layout_height="wrap_content"
41+
android:layout_alignParentBottom="true"
42+
android:layout_centerHorizontal="true"
43+
android:background="#000"
44+
android:text="0"
45+
android:textColor="#FFF"
46+
android:textSize="18sp"
47+
android:visibility="visible"
48+
tools:layout_editor_absoluteX="758dp"
49+
tools:layout_editor_absoluteY="1123dp" />
50+
51+
</RelativeLayout>
52+
53+

0 commit comments

Comments
 (0)