package com.novoda.magicmirror;
import android.Manifest;
import android.app.Dialog;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.view.KeyEvent;
import android.view.WindowManager;
import android.widget.Toast;
import com.novoda.magicmirror.facerecognition.FaceStatusView;
import com.novoda.magicmirror.facerecognition.LookingEyes;
import com.novoda.magicmirror.sfx.FacialExpressionEffects;
import com.novoda.magicmirror.sfx.SfxMappings;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import com.novoda.notils.caster.Views;
import com.novoda.notils.logger.simple.Log;
import com.novoda.magicmirror.facerecognition.CameraSourcePreview;
import com.novoda.magicmirror.facerecognition.FaceCameraSource;
import com.novoda.magicmirror.facerecognition.FaceDetectionUnavailableException;
import com.novoda.magicmirror.facerecognition.FaceExpression;
import com.novoda.magicmirror.facerecognition.FaceReactionSource;
import com.novoda.magicmirror.facerecognition.FaceTracker;
import com.novoda.magicmirror.facerecognition.KeyToFaceMappings;
import com.novoda.magicmirror.facerecognition.KeyboardFaceSource;
import com.novoda.magicmirror.sfx.GlowView;
import com.novoda.magicmirror.sfx.ParticlesLayout;
public class FaceRecognitionActivity extends AppCompatActivity {
private static final int CAMERA_PERMISSION_REQUEST = 0;
private final DeviceInformation deviceInformation = new DeviceInformation();
private FaceReactionSource faceSource;
private CameraSourcePreview preview;
private SystemUIHider systemUIHider;
private FaceStatusView faceStatus;
private LookingEyes lookingEyes;
private GlowView glowView;
private ParticlesLayout particlesView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_face_recognition);
lookingEyes = (LookingEyes) findViewById(R.id.looking_eyes);
faceStatus = (FaceStatusView) findViewById(R.id.status);
preview = (CameraSourcePreview) findViewById(R.id.preview);
glowView = Views.findById(this, R.id.glow_background);
particlesView = Views.findById(this, R.id.particles);
particlesView.initialise();
systemUIHider = new SystemUIHider(findViewById(android.R.id.content));
keepScreenOn();
boolean hasCamera = getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA_FRONT);
if (!hasCamera) {
Toast.makeText(this, R.string.no_camera_available_error, Toast.LENGTH_SHORT).show();
finish();
return;
}
if (isUsingCamera()) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(
this,
new String[]{Manifest.permission.CAMERA},
CAMERA_PERMISSION_REQUEST
);
} else {
tryToCreateCameraSource();
}
displayErrorIfPlayServicesMissing();
} else {
createKeyboardSource();
}
}
private boolean isUsingCamera() {
return !deviceInformation.isEmulator();
}
private void keepScreenOn() {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
private void createKeyboardSource() {
KeyToFaceMappings mappings = KeyToFaceMappings.newInstance();
faceSource = new KeyboardFaceSource(faceListener, mappings);
}
private void tryToCreateCameraSource() {
try {
faceSource = FaceCameraSource.createFrom(this, faceListener, preview);
} catch (FaceDetectionUnavailableException e) {
Toast.makeText(this, R.string.face_detection_not_available_error, Toast.LENGTH_LONG).show();
}
}
private void displayErrorIfPlayServicesMissing() {
int code = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(this);
if (code != ConnectionResult.SUCCESS) {
Dialog dlg = GoogleApiAvailability.getInstance().getErrorDialog(this, code, 101);
dlg.show();
}
}
@Override
protected void onResume() {
super.onResume();
systemUIHider.hideSystemUi();
if (faceSourceHasBeenDefined()) {
faceSource.start();
}
}
private boolean faceSourceHasBeenDefined() {
return faceSource != null;
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == CAMERA_PERMISSION_REQUEST) {
if (isPermissionGranted(grantResults)) {
tryToCreateCameraSource();
} else {
Log.e("User denied CAMERA permission");
finish();
}
}
}
private boolean isPermissionGranted(@NonNull int[] grantResults) {
return grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED;
}
@Override
protected void onPause() {
super.onPause();
preview.stop();
lookingEyes.hide();
systemUIHider.showSystemUi();
}
@Override
protected void onDestroy() {
super.onDestroy();
if (faceSourceHasBeenDefined()) {
faceSource.release();
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (faceSource.onKeyDown(keyCode)) {
return true;
}
return super.onKeyDown(keyCode, event);
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
if (faceSource.onKeyUp(keyCode)) {
return true;
}
return super.onKeyUp(keyCode, event);
}
private final FaceTracker.FaceListener faceListener = new FaceTracker.FaceListener() {
private final SfxMappings mappings = SfxMappings.newInstance();
@Override
public void onNewFace(final FaceExpression expression) {
runOnUiThread(new Runnable() {
@Override
public void run() {
FacialExpressionEffects effects = mappings.forExpression(expression);
glowView.transitionToColor(effects.glowColorRes());
if (effects.hasParticle()) {
particlesView.startParticles(effects.getParticle());
} else {
particlesView.stopParticles();
}
if (expression.isMissing()) {
lookingEyes.show();
faceStatus.hide();
} else {
lookingEyes.hide();
faceStatus.setExpression(expression);
faceStatus.show();
}
}
});
}
};
}