package com.rubenvandeven.emotionhero; import android.Manifest; import android.animation.ArgbEvaluator; import android.animation.ValueAnimator; import android.app.ActivityManager; import android.app.ProgressDialog; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.graphics.Bitmap; import android.support.v4.app.DialogFragment; import android.support.v8.renderscript.RenderScript; import android.graphics.Typeface; import android.support.v4.app.ActivityCompat; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.util.Log; import android.view.SurfaceView; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; import com.affectiva.android.affdex.sdk.Frame; 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.util.List; import io.github.silvaren.easyrs.tools.Nv21Image; public class MirrorMenuActivity extends AppCompatActivity implements Detector.ImageListener, CameraDetector.CameraEventListener, Detector.FaceListener { final static String LOG_TAG = "EmotionHero-Mirror"; public final static String INTENT_EXTRA_SHOW_INTRO = "com.rubenvandeven.emotionhero.INTRO"; private CameraDetector detector; final int PERMISSIONS_REQUEST_CAMERA = 1; int previewWidth = 0; int previewHeight = 0; SurfaceView cameraPreview; ScenarioView scenarioView; LinearLayout mainMenu; TextView messageText; TextView nextButton; TextView readyButton; TextView text1; TextView text2; ImageView logoEmotionHero; boolean has_camera_permission = false; ProgressDialog loadGameDialog; RenderScript rs; Player player; Animation anim; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN); getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD); // kiosk mode if(getSupportActionBar() != null) { getSupportActionBar().hide(); } setContentView(R.layout.activity_mirror_menu); player = Player.getInstance(this); RelativeLayout videoContentLayout = (RelativeLayout) findViewById(R.id.videoContent); logoEmotionHero = (ImageView) findViewById(R.id.logoEmotionHero); messageText = (TextView) findViewById(R.id.messageText); final TextView startButton = (TextView) findViewById(R.id.startButton); TextView highscoresButton = (TextView) findViewById(R.id.highscoresButton); TextView creditsButton = (TextView) findViewById(R.id.creditsButton); TextView settingsButton = (TextView) findViewById(R.id.settingsButton); mainMenu = (LinearLayout) findViewById(R.id.mainMenu); nextButton = (TextView) findViewById(R.id.nextButton); readyButton = (TextView) findViewById(R.id.readyButton); text1 = (TextView) findViewById(R.id.introText1); text2 = (TextView) findViewById(R.id.introText2); Typeface font = Typeface.createFromAsset(getAssets(), "unifont-9.0.02.ttf"); startButton .setTypeface(font); highscoresButton .setTypeface(font); creditsButton .setTypeface(font); settingsButton.setTypeface(font); settingsButton.setVisibility(View.INVISIBLE); // kiosk mode doesn't have settings messageText.setTypeface(font); nextButton.setTypeface(font); readyButton.setTypeface(font); //We create a custom SurfaceView that resizes itself to match the aspect ratio of the incoming camera frames cameraPreview = new SurfaceView(this) { @Override public void onMeasure(int widthSpec, int heightSpec) { int measureWidth = MeasureSpec.getSize(widthSpec); int measureHeight = MeasureSpec.getSize(heightSpec); int maxWidth = MirrorMenuActivity.this.getWindow().getDecorView().getWidth(); int maxHeight = MirrorMenuActivity.this.getWindow().getDecorView().getHeight(); int width; int height; Log.i(LOG_TAG, "Change the camera preview: " + previewWidth + " + " + measureWidth); if (previewHeight == 0 || previewWidth == 0) { width = measureWidth; height = measureHeight; } else { float viewAspectRatio = (float)measureWidth/measureHeight; float cameraPreviewAspectRatio = (float) previewWidth/previewHeight; if (cameraPreviewAspectRatio > viewAspectRatio) { width = measureWidth; height =(int) (measureWidth / cameraPreviewAspectRatio); } else { width = (int) (measureHeight * cameraPreviewAspectRatio); height = measureHeight; } } // make sure we fill the screen! if(width < maxWidth) { float ratio = (float)maxWidth/width; width = maxWidth; height = (int) (ratio * height); } if(height < maxHeight) { float ratio = (float)maxHeight/height; width = (int) (ratio * width); height = maxHeight; } setMeasuredDimension(width,height); } }; RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); // RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(1,1); params.addRule(RelativeLayout.CENTER_IN_PARENT,RelativeLayout.TRUE); cameraPreview.setLayoutParams(params); cameraPreview.setWillNotDraw(false); videoContentLayout.addView(cameraPreview,0); scenarioView = new ScenarioView(this, null); RelativeLayout.LayoutParams scenarioViewParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); videoContentLayout.addView(scenarioView, 1, scenarioViewParams); scenarioView.drawOverlay = true; scenarioView.noFace = true; anim = new AlphaAnimation(0.0f, 1.0f); anim.setDuration(1000); //You can manage the blinking time with this parameter anim.setStartOffset(20); anim.setRepeatMode(Animation.REVERSE); anim.setRepeatCount(Animation.INFINITE); logoEmotionHero.startAnimation(anim); Integer colorFrom = getResources().getColor(R.color.textPrimary); Integer colorTo = getResources().getColor(R.color.textHighlight); ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo); colorAnimation.setDuration(1000); colorAnimation.setRepeatCount(ValueAnimator.INFINITE); colorAnimation.setRepeatMode(ValueAnimator.REVERSE); colorAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animator) { startButton.setTextColor((Integer)animator.getAnimatedValue()); } }); colorAnimation.start(); // merge with 'start button' // highscoresButton.setVisibility(View.GONE); if(!player.getPlayerInfo().canContinueLevel()) { highscoresButton.setVisibility(View.GONE); } else { startButton.setText("Introduction"); highscoresButton.setText("Start"); highscoresButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(MirrorMenuActivity.this, ProgressActivity.class); startActivity(intent); stopDetector(); } }); } creditsButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(MirrorMenuActivity.this, CreditsActivity.class); startActivity(intent); stopDetector(); } }); settingsButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { showSettings(); } }); rs = RenderScript.create(this); startButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { gotoIntro(); } }); nextButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { nextButton.setVisibility(View.GONE); readyButton.setVisibility(View.VISIBLE); text1.setVisibility(View.GONE); text2.setVisibility(View.VISIBLE); } }); readyButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(MirrorMenuActivity.this, ProgressActivity.class); startActivity(intent); stopDetector(); finish(); } }); if(!player.hasSetSnapshotConfirm()) { showSettings(); } // all setup, see wheter we immediately continue to intro: boolean showIntro = getIntent().getBooleanExtra(INTENT_EXTRA_SHOW_INTRO, false); if(showIntro) { gotoIntro(); } } protected void gotoIntro() { if(anim != null) { anim.cancel(); } logoEmotionHero.setVisibility(View.GONE); logoEmotionHero.setAlpha(0f); nextButton.setVisibility(View.VISIBLE); text1.setVisibility(View.VISIBLE); mainMenu.setVisibility(View.GONE); } public void showSettings() { DialogFragment newFragment = SnapshotDialogFragment.newInstance(); newFragment.show(getSupportFragmentManager(), "dialog"); } @Override protected void onResume() { super.onResume(); startDetector(); if(loadGameDialog != null) loadGameDialog.dismiss(); } @Override protected void onPause() { super.onPause(); // stopDetector(); // kiosk mode should never pause ... ActivityManager activityManager = (ActivityManager) getApplicationContext() .getSystemService(Context.ACTIVITY_SERVICE); activityManager.moveTaskToFront(getTaskId(), 0); } void startDetector() { if (detector == null || !detector.isRunning()) { // check permission String permission = "android.permission.CAMERA"; int res = getApplicationContext().checkCallingOrSelfPermission(permission); if (res == PackageManager.PERMISSION_GRANTED) { Log.i(LOG_TAG, "Has camera permission"); has_camera_permission = true; } else { Log.i(LOG_TAG, "No camera permission"); ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, PERMISSIONS_REQUEST_CAMERA); } if(has_camera_permission) { if(detector == null) { // SurfaceView surfaceView = (SurfaceView) findViewById(R.id.surfaceView); detector = new CameraDetector(this, CameraDetector.CameraType.CAMERA_FRONT, cameraPreview, 1, Detector.FaceDetectorMode.LARGE_FACES); // detector.setLicensePath("emotionhero_dev.license"); detector.setDetectAllEmotions(true); detector.setDetectAllAppearances(false); detector.setDetectAllEmojis(false); detector.setDetectAllExpressions(false); detector.setMaxProcessRate(12); detector.setImageListener(this); detector.setOnCameraEventListener(this); detector.setFaceListener(this); } detector.start(); setText("STARTING..."); Log.d(LOG_TAG, Boolean.toString(detector.isRunning())); } } } void stopDetector() { if (detector != null && detector.isRunning()) { detector.stop(); } } @Override /** * Detector callback gives the faces found so we can match their hits to the given scenario. */ public void onImageResults(List list, Frame frame, float timestamp) { if (list == null || list.size() == 0) { setText("Show me your face"); return; } else { hideText(); Face face = list.get(0); scenarioView.setCurrentAttributeScoresForFace(face); } } @Override /** * For CameraDetector.CameraEventListener * Used to scale video preview output */ public void onCameraSizeSelected(int width, int height, Frame.ROTATE rotate) { if (rotate == Frame.ROTATE.BY_90_CCW || rotate == Frame.ROTATE.BY_90_CW) { previewWidth = height; previewHeight = width; } else { previewHeight = height; previewWidth = width; } Log.i(LOG_TAG, "onCameraSize "+previewWidth +"x"+previewHeight); cameraPreview.requestLayout(); } @Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { switch (requestCode) { case PERMISSIONS_REQUEST_CAMERA: { // If request is cancelled, the result arrays are empty. if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { has_camera_permission = true; startDetector(); } else { has_camera_permission = false; Toast errorMsg = Toast.makeText(this, R.string.camera_required, Toast.LENGTH_LONG); errorMsg.show(); } return; } // other 'case' lines to check for other // permissions this app might request } } @Override public void onFaceDetectionStarted() { hideText(); scenarioView.noFace = false; } @Override public void onFaceDetectionStopped() { scenarioView.noFace = true; } public void setText(String text) { messageText.setVisibility(View.VISIBLE); messageText.setText(text); } public void hideText() { messageText.setVisibility(View.GONE); } /** * For kiosk mode only */ @Override public void onBackPressed() { // nothing to do here // … really } /** * For kioskmode * @param hasFocus */ @Override public void onWindowFocusChanged(boolean hasFocus) { super.onWindowFocusChanged(hasFocus); if(!hasFocus) { // Close every kind of system dialog Intent closeDialog = new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS); sendBroadcast(closeDialog); } } }