diff --git a/README.md b/README.md
index 264b214..12d725d 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@ In order to use this project, you will need to:
- Obtain the Affectiva Android SDK (visit http://www.affectiva.com/solutions/apis-sdks/)
- Copy the contents of the SDK's assets folder into this project's app/src/main/assets folder
- Copy the contents of the SDK's libs folder into this project's app/libs folder
-- Copy the armeabi-v7a folder (found in the SDK libs folder) into this project's app/native-libs folder
+- Copy the armeabi-v7a folder (found in the SDK libs folder) into this project's app/jniLibs folder
- Copy your license file to this project's app/src/main/assets/Affdex folder and rename to license.txt
- Build the project
- Run the app and smile!
diff --git a/app/.gitignore b/app/.gitignore
index 5af3699..3f6af81 100644
--- a/app/.gitignore
+++ b/app/.gitignore
@@ -3,6 +3,6 @@
/jniLibs/armeabi-v7a
/libs/Affdex-sdk.jar
/libs/Affdex-sdk-javadoc.jar
-/src/main/assets/Affdex/*.license
+/src/main/assets/Affdex/*license*
/src/main/assets/Affdex/Classifiers
/src/main/assets/Affdex/Classifiers/v_9
diff --git a/app/app.iml b/app/app.iml
index a7e63e1..73426a8 100644
--- a/app/app.iml
+++ b/app/app.iml
@@ -67,6 +67,8 @@
+
+
@@ -80,6 +82,9 @@
+
+
+
diff --git a/app/build.gradle b/app/build.gradle
index 1d24c2a..bf51eca 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -6,7 +6,7 @@ android {
defaultConfig {
applicationId "com.affectiva.affdexme"
- minSdkVersion 14
+ minSdkVersion 16
targetSdkVersion 23
versionCode 15
versionName "2.1.0"
@@ -41,14 +41,14 @@ dependencies {
compile files('libs/Affdex-sdk-javadoc.jar')
//include dependencies
+ compile 'com.android.support:support-v4:23.1.1'
+ compile 'com.android.support:appcompat-v7:23.1.1'
compile 'com.squareup.dagger:dagger:1.2.2'
compile 'javax.inject:javax.inject:1'
//although the use of the CameraDetector class in this project does not require it, you may have to include
//the following dependencies if you use other features of the Affdex SDK
// compile 'com.google.code.gson:gson:2.4'
-// compile 'com.android.support:support-v4:23.1.1'
-// compile 'com.android.support:appcompat-v7:23.1.1'
// compile 'com.android.support:support-v13:23.1.1'
// compile 'com.google.android.gms:play-services:8.4.0'
// compile 'com.google.android.gms:play-services-ads:8.4.0'
diff --git a/app/jniLibs/READ.ME b/app/jniLibs/READ.ME
index e1be708..232ed8e 100644
--- a/app/jniLibs/READ.ME
+++ b/app/jniLibs/READ.ME
@@ -1,3 +1,3 @@
Place the native library files here.
-amreabi-v7a/libaffdexface_jni.so
\ No newline at end of file
+armeabi-v7a/libaffdexface_jni.so
diff --git a/app/libs/READ.ME b/app/libs/READ.ME
index d79e964..c740ba4 100644
--- a/app/libs/READ.ME
+++ b/app/libs/READ.ME
@@ -1,4 +1,6 @@
Place the Affdex SDK JARs here.
Affdex-sdk.jar
-Affdex-sdk-javadoc.jar
\ No newline at end of file
+Affdex-sdk-javadoc.jar
+dagger-*.java
+javax.inject-1.jar
diff --git a/app/src/main/assets/Affdex/READ.ME b/app/src/main/assets/Affdex/READ.ME
index 1ec813e..e5a2081 100644
--- a/app/src/main/assets/Affdex/READ.ME
+++ b/app/src/main/assets/Affdex/READ.ME
@@ -1,12 +1,4 @@
Place license file and Classifiers folder here.
-xxxxxx.license
-Classifiers
-Classifiers/v_9
-Classifiers/v_9/face_model_3d.bin
-Classifiers/v_9/CT_pack/*
-Classifiers/v_9/haarcascade/*
-Classifiers/v_9/new_pack/*
-Classifiers/v_9/noctali0.83/*
-Classifiers/v_9/PA_pack/*
-Classifiers/v_9/production_config/*
+license.txt
+Classifiers/v_9/*
diff --git a/app/src/main/java/com/affectiva/affdexme/MainActivity.java b/app/src/main/java/com/affectiva/affdexme/MainActivity.java
index 0ce160b..325167f 100644
--- a/app/src/main/java/com/affectiva/affdexme/MainActivity.java
+++ b/app/src/main/java/com/affectiva/affdexme/MainActivity.java
@@ -1,6 +1,7 @@
package com.affectiva.affdexme;
-import android.app.Activity;
+import android.Manifest;
+import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
@@ -8,14 +9,20 @@ import android.graphics.Typeface;
import android.os.Bundle;
import android.os.SystemClock;
import android.preference.PreferenceManager;
-import android.util.Log;
+import android.support.annotation.NonNull;
+import android.support.v4.app.ActivityCompat;
+import android.support.v4.content.ContextCompat;
+import android.support.v7.app.AlertDialog;
+import android.support.v7.app.AppCompatActivity;
import android.util.DisplayMetrics;
+import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
+import android.widget.Button;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
@@ -23,18 +30,16 @@ import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
-import java.io.BufferedReader;
-import java.io.ByteArrayInputStream;
-import java.io.InputStreamReader;
-import java.lang.reflect.Method;
-import java.util.List;
-
import com.affectiva.android.affdex.sdk.Frame;
import com.affectiva.android.affdex.sdk.Frame.ROTATE;
import com.affectiva.android.affdex.sdk.detector.CameraDetector;
import com.affectiva.android.affdex.sdk.detector.Detector;
import com.affectiva.android.affdex.sdk.detector.Face;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+
/*
* AffdexMe is an app that demonstrates the use of the Affectiva Android SDK. It uses the
* front-facing camera on your Android device to view, process and analyze live video of your face.
@@ -67,15 +72,23 @@ import com.affectiva.android.affdex.sdk.detector.Face;
* Copyright (c) 2014 Affectiva. All rights reserved.
*/
-public class MainActivity extends Activity
- implements Detector.FaceListener, Detector.ImageListener, View.OnTouchListener, CameraDetector.CameraEventListener {
+public class MainActivity extends AppCompatActivity
+ implements Detector.FaceListener, Detector.ImageListener, CameraDetector.CameraEventListener,
+ View.OnTouchListener, ActivityCompat.OnRequestPermissionsResultCallback {
- private static final String LOG_TAG = "Affectiva";
public static final int NUM_METRICS_DISPLAYED = 6;
-
+ private static final String LOG_TAG = "Affectiva";
+ //Permission-related constants and variables
+ private static final int AFFDEXME_PERMISSIONS_REQUEST = 42; //value is arbitrary (between 0 and 255)
+ private boolean cameraPermissionsAvailable = false;
+ private boolean storagePermissionsAvailable = false;
+ //Camera variables
+ int cameraPreviewWidth = 0;
+ int cameraPreviewHeight = 0;
+ CameraDetector.CameraType cameraType;
+ boolean mirrorPoints = false;
//Affectiva SDK Object
private CameraDetector detector = null;
-
//MetricsManager View UI Objects
private RelativeLayout metricViewLayout;
private LinearLayout leftMetricsLayout;
@@ -86,34 +99,28 @@ public class MainActivity extends Activity
private TextView fpsPct;
private TextView pleaseWaitTextView;
private ProgressBar progressBar;
-
//Other UI objects
private ViewGroup activityLayout; //top-most ViewGroup in which all content resides
private RelativeLayout mainLayout; //layout, to be resized, containing all UI elements
private RelativeLayout progressBarLayout; //layout used to show progress circle while camera is starting
+ private LinearLayout permissionsUnavailableLayout; //layout used to notify the user that not enough permissions have been granted to use the app
private SurfaceView cameraView; //SurfaceView used to display camera images
private DrawingView drawingView; //SurfaceView containing its own thread, used to draw facial tracking dots
private ImageButton settingsButton;
private ImageButton cameraButton;
-
+ private Button retryPermissionsButton;
//Application settings variables
private int detectorProcessRate;
private boolean isMenuVisible = false;
private boolean isFPSVisible = false;
private boolean isMenuShowingForFirstTime = true;
-
//Frames Per Second (FPS) variables
private long firstSystemTime = 0;
private float numberOfFrames = 0;
private long timeToUpdate = 0;
-
//Camera-related variables
private boolean isFrontFacingCameraDetected = true;
private boolean isBackFacingCameraDetected = true;
- int cameraPreviewWidth = 0;
- int cameraPreviewHeight = 0;
- CameraDetector.CameraType cameraType;
- boolean mirrorPoints = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -122,12 +129,110 @@ public class MainActivity extends Activity
setContentView(R.layout.activity_main);
initializeUI();
+ checkForDangerousPermissions();
determineCameraAvailability();
initializeCameraDetector();
}
+ private void checkForDangerousPermissions() {
+ cameraPermissionsAvailable =
+ ContextCompat.checkSelfPermission(
+ getApplicationContext(),
+ Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED;
+ storagePermissionsAvailable =
+ ContextCompat.checkSelfPermission(
+ getBaseContext(),
+ Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
+
+ if (!cameraPermissionsAvailable || !storagePermissionsAvailable) {
+
+ // Should we show an explanation?
+ if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) ||
+ ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.CAMERA)) {
+
+ // Show an explanation to the user *asynchronously* -- don't block
+ // this thread waiting for the user's response! After the user
+ // sees the explanation, try again to request the permission.
+ showPermissionExplanationDialog();
+ } else {
+ // No explanation needed, we can request the permission.
+ requestNeededPermissions();
+ }
+ }
+ }
+
+ private void requestNeededPermissions() {
+ List neededPermissions = new ArrayList<>();
+
+ if (!cameraPermissionsAvailable) {
+ neededPermissions.add(Manifest.permission.CAMERA);
+ }
+ if (!storagePermissionsAvailable) {
+ neededPermissions.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
+ }
+
+ ActivityCompat.requestPermissions(
+ this,
+ neededPermissions.toArray(new String[neededPermissions.size()]),
+ AFFDEXME_PERMISSIONS_REQUEST);
+
+ // AFFDEXME_PERMISSIONS_REQUEST is an app-defined int constant that must be between 0 and 255.
+ // The callback method gets the result of the request.
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+
+ if (requestCode == AFFDEXME_PERMISSIONS_REQUEST) {
+ for (int i = 0; i < permissions.length; i++) {
+ String permission = permissions[i];
+ int grantResult = grantResults[i];
+
+ if (permission.equals(Manifest.permission.CAMERA)) {
+ cameraPermissionsAvailable = (grantResult == PackageManager.PERMISSION_GRANTED);
+ }
+ if (permission.equals(Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
+ storagePermissionsAvailable = (grantResult == PackageManager.PERMISSION_GRANTED);
+ }
+ }
+ }
+
+ if (!cameraPermissionsAvailable || !storagePermissionsAvailable) {
+ permissionsUnavailableLayout.setVisibility(View.VISIBLE);
+ } else {
+ permissionsUnavailableLayout.setVisibility(View.GONE);
+ }
+ }
+
+ private void showPermissionExplanationDialog() {
+ final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(
+ getApplicationContext());
+
+ // set title
+ alertDialogBuilder.setTitle(getResources().getString(R.string.insufficient_permissions));
+
+ // set dialog message
+ alertDialogBuilder
+ .setMessage(getResources().getString(R.string.permissions_needed_explanation))
+ .setCancelable(false)
+ .setPositiveButton(getResources().getString(R.string.understood), new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ dialog.cancel();
+ requestNeededPermissions();
+ }
+ });
+
+ // create alert dialog
+ AlertDialog alertDialog = alertDialogBuilder.create();
+
+ // show it
+ alertDialog.show();
+ }
+
+
/**
* We check to make sure the device has a front-facing camera.
* If it does not, we obscure the app with a notice informing the user they cannot
@@ -161,6 +266,7 @@ public class MainActivity extends Activity
//Get handles to UI objects
activityLayout = (ViewGroup) findViewById(android.R.id.content);
progressBarLayout = (RelativeLayout) findViewById(R.id.progress_bar_cover);
+ permissionsUnavailableLayout = (LinearLayout) findViewById(R.id.permissionsUnavialableLayout);
metricViewLayout = (RelativeLayout) findViewById(R.id.metric_view_group);
leftMetricsLayout = (LinearLayout) findViewById(R.id.left_metrics);
rightMetricsLayout = (LinearLayout) findViewById(R.id.right_metrics);
@@ -173,6 +279,7 @@ public class MainActivity extends Activity
cameraButton = (ImageButton) findViewById(R.id.camera_button);
progressBar = (ProgressBar) findViewById(R.id.progress_bar);
pleaseWaitTextView = (TextView) findViewById(R.id.please_wait_textview);
+ retryPermissionsButton = (Button) findViewById(R.id.retryPermissionsButton);
//Initialize views to display metrics
metricNames = new TextView[NUM_METRICS_DISPLAYED];
@@ -235,6 +342,13 @@ public class MainActivity extends Activity
}
});
+
+ retryPermissionsButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ requestNeededPermissions();
+ }
+ });
}
void initializeCameraDetector() {
@@ -245,9 +359,8 @@ public class MainActivity extends Activity
detector = new CameraDetector(this, CameraDetector.CameraType.CAMERA_FRONT, cameraView);
- // update the license path here if you name your file something else
-// detector.setLicensePath("license.txt");
- detector.setLicensePath("Affectiva.license");
+ // update the license path here if you name your file something else
+ detector.setLicensePath("license.txt");
detector.setImageListener(this);
detector.setFaceListener(this);
detector.setOnCameraEventListener(this);
@@ -259,6 +372,7 @@ public class MainActivity extends Activity
@Override
public void onResume() {
super.onResume();
+ checkForDangerousPermissions();
restoreApplicationSettings();
setMenuVisible(true);
isMenuShowingForFirstTime = true;
@@ -274,19 +388,19 @@ public class MainActivity extends Activity
detectorProcessRate = PreferencesUtils.getFrameProcessingRate(sharedPreferences);
detector.setMaxProcessRate(detectorProcessRate);
- if (sharedPreferences.getBoolean("fps",isFPSVisible)) { //restore isFPSMetricVisible
+ if (sharedPreferences.getBoolean("fps", isFPSVisible)) { //restore isFPSMetricVisible
setFPSVisible(true);
} else {
setFPSVisible(false);
}
- if (sharedPreferences.getBoolean("track",drawingView.getDrawPointsEnabled())) { //restore isTrackingDotsVisible
+ if (sharedPreferences.getBoolean("track", drawingView.getDrawPointsEnabled())) { //restore isTrackingDotsVisible
setTrackPoints(true);
} else {
setTrackPoints(false);
}
- if (sharedPreferences.getBoolean("measurements",drawingView.getDrawMeasurementsEnabled())) { //restore show measurements
+ if (sharedPreferences.getBoolean("measurements", drawingView.getDrawMeasurementsEnabled())) { //restore show measurements
setShowMeasurements(true);
} else {
setShowMeasurements(false);
@@ -294,15 +408,15 @@ public class MainActivity extends Activity
//populate metric displays
for (int n = 0; n < NUM_METRICS_DISPLAYED; n++) {
- activateMetric(n,PreferencesUtils.getMetricFromPrefs(sharedPreferences, n));
+ activateMetric(n, PreferencesUtils.getMetricFromPrefs(sharedPreferences, n));
}
}
/**
* Populates a TextView to display a metric name and readies a MetricDisplay to display the value.
* Uses reflection to:
- * -enable the corresponding metric in the Detector object by calling Detector.setDetect()
- * -save the Method object that will be invoked on the Face object received in onImageResults() to get the metric score
+ * -enable the corresponding metric in the Detector object by calling Detector.setDetect()
+ * -save the Method object that will be invoked on the Face object received in onImageResults() to get the metric score
*/
void activateMetric(int index, MetricsManager.Metrics metric) {
metricNames[index].setText(MetricsManager.getUpperCaseName(metric));
@@ -322,10 +436,10 @@ public class MainActivity extends Activity
metricDisplays[index].setIsShadedMetricView(false);
}
} else if (metric.getType() == MetricsManager.MetricType.Expression) {
- getFaceScoreMethod = Face.Expressions.class.getMethod("get" + MetricsManager.getCamelCase(metric),null);
+ getFaceScoreMethod = Face.Expressions.class.getMethod("get" + MetricsManager.getCamelCase(metric), null);
}
} catch (Exception e) {
- Log.e(LOG_TAG,String.format("Error using reflection to generate methods for %s",metric.toString()));
+ Log.e(LOG_TAG, String.format("Error using reflection to generate methods for %s", metric.toString()));
}
metricDisplays[index].setMetricToDisplay(metric, getFaceScoreMethod);
@@ -333,7 +447,7 @@ public class MainActivity extends Activity
/**
* Reset the variables used to calculate processed frames per second.
- * **/
+ **/
public void resetFPSCalculations() {
firstSystemTime = SystemClock.elapsedRealtime();
timeToUpdate = firstSystemTime + 1000L;
@@ -359,6 +473,12 @@ public class MainActivity extends Activity
void mainWindowResumedTasks() {
+ //Notify the user that they can't use the app without authorizing these permissions.
+ if (!cameraPermissionsAvailable || !storagePermissionsAvailable) {
+ permissionsUnavailableLayout.setVisibility(View.VISIBLE);
+ return;
+ }
+
startDetector();
if (!drawingView.isDimensionsNeeded()) {
@@ -390,7 +510,6 @@ public class MainActivity extends Activity
}
-
@Override
public void onFaceDetectionStarted() {
leftMetricsLayout.animate().alpha(1); //make left and right metrics appear
@@ -435,7 +554,7 @@ public class MainActivity extends Activity
//update metrics with latest face information. The metrics are displayed on a MetricView, a custom view with a .setScore() method.
for (MetricDisplay metricDisplay : metricDisplays) {
- updateMetricScore(metricDisplay,face);
+ updateMetricScore(metricDisplay, face);
}
/**
@@ -445,7 +564,7 @@ public class MainActivity extends Activity
*/
if (drawingView.getDrawPointsEnabled() || drawingView.getDrawMeasurementsEnabled()) {
drawingView.setMetrics(face.measurements.orientation.getRoll(), face.measurements.orientation.getYaw(), face.measurements.orientation.getPitch(), face.measurements.getInterocularDistance(), face.emotions.getValence());
- drawingView.updatePoints(face.getFacePoints(),mirrorPoints);
+ drawingView.updatePoints(face.getFacePoints(), mirrorPoints);
}
}
@@ -460,13 +579,13 @@ public class MainActivity extends Activity
try {
if (metric.getType() == MetricsManager.MetricType.Emotion) {
- score = (Float) metricDisplay.getFaceScoreMethod().invoke(face.emotions,null);
+ score = (Float) metricDisplay.getFaceScoreMethod().invoke(face.emotions, null);
metricDisplay.setScore(score);
} else if (metric.getType() == MetricsManager.MetricType.Expression) {
- score = (Float) metricDisplay.getFaceScoreMethod().invoke(face.expressions,null);
+ score = (Float) metricDisplay.getFaceScoreMethod().invoke(face.expressions, null);
}
} catch (Exception e) {
- Log.e(LOG_TAG,String.format("Error using reflecting to get %s score from face.",metric.toString()));
+ Log.e(LOG_TAG, String.format("Error using reflecting to get %s score from face.", metric.toString()));
}
metricDisplay.setScore(score);
}
@@ -482,8 +601,8 @@ public class MainActivity extends Activity
numberOfFrames += 1;
long currentTime = SystemClock.elapsedRealtime();
if (currentTime > timeToUpdate) {
- float framesPerSecond = (numberOfFrames/(float)(currentTime - firstSystemTime))*1000f;
- fpsPct.setText(String.format(" %.1f",framesPerSecond));
+ float framesPerSecond = (numberOfFrames / (float) (currentTime - firstSystemTime)) * 1000f;
+ fpsPct.setText(String.format(" %.1f", framesPerSecond));
timeToUpdate = currentTime + 1000L;
}
}
@@ -508,7 +627,7 @@ public class MainActivity extends Activity
try {
detector.stop();
} catch (Exception e) {
- Log.e(LOG_TAG,e.getMessage());
+ Log.e(LOG_TAG, e.getMessage());
}
}
@@ -517,11 +636,10 @@ public class MainActivity extends Activity
}
-
/**
* When the user taps the screen, hide the menu if it is visible and show it if it is hidden.
- * **/
- void setMenuVisible(boolean b){
+ **/
+ void setMenuVisible(boolean b) {
isMenuShowingForFirstTime = false;
isMenuVisible = b;
if (b) {
@@ -533,8 +651,7 @@ public class MainActivity extends Activity
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN);
- }
- else {
+ } else {
//We hide the navigation bar
getWindow().getDecorView().setSystemUiVisibility(
@@ -613,7 +730,7 @@ public class MainActivity extends Activity
cameraPreviewWidth = cameraWidth;
cameraPreviewHeight = cameraHeight;
}
- drawingView.setThickness((int)(cameraPreviewWidth/100f));
+ drawingView.setThickness((int) (cameraPreviewWidth / 100f));
mainLayout.post(new Runnable() {
@Override
@@ -627,21 +744,21 @@ public class MainActivity extends Activity
if (cameraPreviewWidth == 0 || cameraPreviewHeight == 0 || layoutWidth == 0 || layoutHeight == 0)
return;
- float layoutAspectRatio = (float)layoutWidth/layoutHeight;
- float cameraPreviewAspectRatio = (float)cameraPreviewWidth/cameraPreviewHeight;
+ float layoutAspectRatio = (float) layoutWidth / layoutHeight;
+ float cameraPreviewAspectRatio = (float) cameraPreviewWidth / cameraPreviewHeight;
int newWidth;
int newHeight;
if (cameraPreviewAspectRatio > layoutAspectRatio) {
newWidth = layoutWidth;
- newHeight =(int) (layoutWidth / cameraPreviewAspectRatio);
+ newHeight = (int) (layoutWidth / cameraPreviewAspectRatio);
} else {
newWidth = (int) (layoutHeight * cameraPreviewAspectRatio);
newHeight = layoutHeight;
}
- drawingView.updateViewDimensions(newWidth,newHeight,cameraPreviewWidth,cameraPreviewHeight);
+ drawingView.updateViewDimensions(newWidth, newHeight, cameraPreviewWidth, cameraPreviewHeight);
ViewGroup.LayoutParams params = mainLayout.getLayoutParams();
params.height = newHeight;
@@ -662,14 +779,14 @@ public class MainActivity extends Activity
cameraType = CameraDetector.CameraType.CAMERA_BACK;
mirrorPoints = false;
} else {
- Toast.makeText(this,"No back-facing camera found",Toast.LENGTH_LONG).show();
+ Toast.makeText(this, "No back-facing camera found", Toast.LENGTH_LONG).show();
}
} else if (cameraType == CameraDetector.CameraType.CAMERA_BACK) {
if (isFrontFacingCameraDetected) {
cameraType = CameraDetector.CameraType.CAMERA_FRONT;
mirrorPoints = true;
} else {
- Toast.makeText(this,"No front-facing camera found",Toast.LENGTH_LONG).show();
+ Toast.makeText(this, "No front-facing camera found", Toast.LENGTH_LONG).show();
}
}
@@ -678,7 +795,7 @@ public class MainActivity extends Activity
try {
detector.setCameraType(cameraType);
} catch (Exception e) {
- Log.e(LOG_TAG,e.getMessage());
+ Log.e(LOG_TAG, e.getMessage());
}
}
}
diff --git a/app/src/main/java/com/affectiva/affdexme/MetricDisplay.java b/app/src/main/java/com/affectiva/affdexme/MetricDisplay.java
index 42f64f2..ea8888e 100644
--- a/app/src/main/java/com/affectiva/affdexme/MetricDisplay.java
+++ b/app/src/main/java/com/affectiva/affdexme/MetricDisplay.java
@@ -69,7 +69,7 @@ public class MetricDisplay extends View {
textPaint.setColor(a.getColor(R.styleable.custom_attributes_textColor, Color.BLACK));
textSize = a.getDimensionPixelSize(R.styleable.custom_attributes_textSize, textSize);
textPaint.setTextSize(textSize);
- halfWidth = a.getDimensionPixelSize(R.styleable.custom_attributes_barLength,100)/2;
+ halfWidth = a.getDimensionPixelSize(R.styleable.custom_attributes_metricBarLength,100)/2;
a.recycle();
} else {
textPaint.setColor(Color.BLACK);
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
index 8378a3a..138c18f 100644
--- a/app/src/main/res/layout/activity_main.xml
+++ b/app/src/main/res/layout/activity_main.xml
@@ -1,93 +1,102 @@
+ tools:context=".MainActivity">
+
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:layout_centerInParent="true" />
+
-
+
+
+ layout="@layout/metric_layout" />
+
+ android:layout_margin="@dimen/settings_button_margin"
+ android:background="@null"
+ android:contentDescription="@string/settings_content_description"
+ android:onClick="settings_button_click"
+ android:scaleType="fitCenter"
+ android:src="@drawable/settings_button_selector" />
+
+ android:layout_margin="@dimen/settings_button_margin"
+ android:background="@null"
+ android:contentDescription="Switch camera button"
+ android:onClick="camera_button_click"
+ android:scaleType="fitCenter"
+ android:src="@drawable/camera_button_selector" />
+
+ android:layout_centerVertical="true"
+ android:text="@string/loading"
+ android:textSize="@dimen/please_wait_textview_size" />
+
+ android:paddingRight="10dp" />
+
+ android:padding="20sp"
+ android:text="@string/not_found"
+ android:textColor="#CCCCCC"
+ android:textSize="20sp"
+ android:visibility="gone" />
diff --git a/app/src/main/res/layout/insufficent_permissions_panel.xml b/app/src/main/res/layout/insufficent_permissions_panel.xml
new file mode 100644
index 0000000..c7c3568
--- /dev/null
+++ b/app/src/main/res/layout/insufficent_permissions_panel.xml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml
index aaf87b2..b008135 100644
--- a/app/src/main/res/values/attrs.xml
+++ b/app/src/main/res/values/attrs.xml
@@ -3,7 +3,7 @@
-
+
diff --git a/app/src/main/res/values/metricStylePct.xml b/app/src/main/res/values/metricStylePct.xml
index 1d43135..9f7f8c8 100644
--- a/app/src/main/res/values/metricStylePct.xml
+++ b/app/src/main/res/values/metricStylePct.xml
@@ -6,6 +6,6 @@
- center
- @color/letter_gray
- @dimen/pct_text_size
- - @dimen/metric_view_bar_length
+ - @dimen/metric_view_bar_length
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 20a5b8e..37b1e42 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -6,6 +6,11 @@
Loading…
Settings
+ Insufficient Permissions
+ This app requires the permission to access your camera to be able to gather facial images to process, and permission to write to the storage on your device so that we can temporarily store video data there while we process it.
+ Error
+ Understood
+
Clear All
0 metrics chosen.
@@ -31,4 +36,5 @@
Show FPS
Display the actual processed frames per second.
+ Retry
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
index 4f3a6db..2a85e88 100644
--- a/app/src/main/res/values/styles.xml
+++ b/app/src/main/res/values/styles.xml
@@ -1,5 +1,5 @@
-