uk.ac.horizon.artcodes.scanner.ScannerActivity.java Source code

Java tutorial

Introduction

Here is the source code for uk.ac.horizon.artcodes.scanner.ScannerActivity.java

Source

/*
 * Artcodes recognises a different marker scheme that allows the
 * creation of aesthetically pleasing, even beautiful, codes.
 * Copyright (C) 2013-2016  The University of Nottingham
 *
 *     This program is free software: you can redistribute it and/or modify
 *     it under the terms of the GNU Affero General Public License as published
 *     by the Free Software Foundation, either version 3 of the License, or
 *     (at your option) any later version.
 *
 *     This program is distributed in the hope that it will be useful,
 *     but WITHOUT ANY WARRANTY; without even the implied warranty of
 *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *     GNU Affero General Public License for more details.
 *
 *     You should have received a copy of the GNU Affero General Public License
 *     along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package uk.ac.horizon.artcodes.scanner;

import android.Manifest;
import android.annotation.TargetApi;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.ColorStateList;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffColorFilter;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.ColorInt;
import android.support.annotation.DrawableRes;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v4.graphics.drawable.DrawableCompat;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.google.common.collect.Lists;
import com.google.gson.Gson;

import java.util.List;

import uk.ac.horizon.artcodes.animator.TextAnimator;
import uk.ac.horizon.artcodes.animator.VisibilityAnimator;
import uk.ac.horizon.artcodes.camera.CameraView;
import uk.ac.horizon.artcodes.detect.ArtcodeDetector;
import uk.ac.horizon.artcodes.detect.DetectorCallback;
import uk.ac.horizon.artcodes.detect.DetectorSetting;
import uk.ac.horizon.artcodes.detect.handler.CodeDetectionHandler;
import uk.ac.horizon.artcodes.detect.handler.MarkerCodeDetectionHandler;
import uk.ac.horizon.artcodes.model.Action;
import uk.ac.horizon.artcodes.model.Experience;

public class ScannerActivity extends AppCompatActivity {
    private static final int CAMERA_PERMISSION_REQUEST = 47;
    private LinearLayout settingIcons;
    protected ProgressBar progressBar;
    private ArtcodeDetector detector;
    private Experience experience;
    private VisibilityAnimator menuAnimator;
    private TextAnimator textAnimator;
    protected CameraView cameraView;

    @SuppressWarnings("UnusedParameters")
    public void hideMenu(View view) {
        menuAnimator.hideView();
    }

    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
    private void hideSystemUI() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
            getWindow().getDecorView().setSystemUiVisibility(
                    View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
        }
    }

    protected View actionView;
    protected VisibilityAnimator actionAnimator;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);

        hideSystemUI();

        setContentView(R.layout.scanner);

        settingIcons = (LinearLayout) findViewById(R.id.settingsSwitches);
        progressBar = (ProgressBar) findViewById(R.id.progressBar);
        cameraView = (CameraView) findViewById(R.id.cameraView);

        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        if (getSupportActionBar() != null) {
            getSupportActionBar().setDisplayShowTitleEnabled(false);
        }

        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[] { Manifest.permission.CAMERA },
                    CAMERA_PERMISSION_REQUEST);
        }

        menuAnimator = new VisibilityAnimator(findViewById(R.id.settingsMenu),
                findViewById(R.id.settingsMenuButton));
        TextView settingsFeedback = (TextView) findViewById(R.id.settingsFeedback);
        textAnimator = new TextAnimator(settingsFeedback);

        ViewGroup bottomView = (ViewGroup) findViewById(R.id.bottomView);
        if (bottomView != null) {
            actionView = getLayoutInflater().inflate(R.layout.scanner_action, bottomView, false);
            bottomView.addView(actionView);
            actionAnimator = new VisibilityAnimator(actionView);
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            progressBar.setIndeterminateTintList(ColorStateList.valueOf(0xff33b5e5));
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
            @NonNull int[] grantResults) {
        switch (requestCode) {
        case CAMERA_PERMISSION_REQUEST: {
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                startScanning();
            } else {
                Log.i("a", "Permission not granted");
                // TODO
            }
        }
        }
    }

    public void loaded(Experience experience) {
        this.experience = experience;
        setExperienceStyle();
        startScanning();
    }

    /**
     * This function sets the colors of the scan screen (only if the experience contains colors).
     */
    public void setExperienceStyle() {
        if (this.experience != null) {
            if (this.experience.getBackgroundColor() != null || this.experience.getForegroundColor() != null) {

                if (this.experience.getBackgroundColor() != null) {
                    View topFrame = findViewById(R.id.topView);
                    View bottomFrame = findViewById(R.id.bottomView);
                    int backgroundColor = Color.parseColor(this.experience.getBackgroundColor());
                    // If no transparency is set add default transparency to background:
                    if (this.experience.getBackgroundColor().length() <= 7)
                        backgroundColor &= 0xbbffffff;
                    if (topFrame != null)
                        topFrame.setBackgroundColor(backgroundColor);
                    if (bottomFrame != null)
                        bottomFrame.setBackgroundColor(backgroundColor);
                }

                if (this.experience.getForegroundColor() != null) {
                    int foregroundColor = Color.parseColor(this.experience.getForegroundColor());
                    Toolbar v = (Toolbar) findViewById(R.id.toolbar);
                    if (v != null) {
                        v.setTitleTextColor(foregroundColor);
                        // set back icon color:
                        try {
                            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                                v.getNavigationIcon().setTint(foregroundColor);
                            } else {
                                v.getNavigationIcon().setColorFilter(
                                        new PorterDuffColorFilter(foregroundColor, PorterDuff.Mode.MULTIPLY));
                            }
                        } catch (NullPointerException e) {
                            Log.w("", "Exception setting toolbar icon colour.", e);
                        }
                    }

                    TextView scanScreenTextTitle = (TextView) findViewById(R.id.scanScreenTextTitle);
                    if (scanScreenTextTitle != null) {
                        scanScreenTextTitle.setTextColor(foregroundColor);
                    }
                    TextView scanScreenTextDesc = (TextView) findViewById(R.id.scanScreenTextDesc);
                    if (scanScreenTextDesc != null) {
                        scanScreenTextDesc.setTextColor(foregroundColor);
                    }
                }

            }

            if (this.experience.getHighlightBackgroundColor() != null
                    && this.experience.getHighlightForegroundColor() != null) {
                int foregroundColor = Color.parseColor(this.experience.getHighlightForegroundColor());
                int backgroundColor = Color.parseColor(this.experience.getHighlightBackgroundColor());

                Button b = (Button) findViewById(R.id.scan_event_button);
                if (b != null) {
                    b.setTextColor(foregroundColor);
                    b.setBackgroundColor(backgroundColor);
                }
                ProgressBar pb = (ProgressBar) findViewById(R.id.progressBar);
                if (pb != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                    pb.setIndeterminateTintList(ColorStateList.valueOf(backgroundColor));
                }
            }

            if (this.experience.getScanScreenTextTitle() != null) {
                TextView textView = (TextView) findViewById(R.id.scanScreenTextTitle);
                if (textView != null) {
                    textView.setVisibility(View.VISIBLE);
                    textView.setText(this.experience.getScanScreenTextTitle());
                }
            }
            if (this.experience.getScanScreenTextDesciption() != null) {
                TextView textView = (TextView) findViewById(R.id.scanScreenTextDesc);
                if (textView != null) {
                    textView.setVisibility(View.VISIBLE);
                    textView.setText(this.experience.getScanScreenTextDesciption());
                }
            }

        }
    }

    @SuppressWarnings("UnusedParameters")
    public void showMenu(View view) {
        createSettingsUI(detector.getSettings());
        menuAnimator.showView();
    }

    protected Experience getExperience() {
        return experience;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (item.getItemId() == android.R.id.home) {
            if (getCallingActivity() != null) {
                setResult(RESULT_CANCELED);
                finish();
                return true;
            }
        }
        return super.onOptionsItemSelected(item);
    }

    private void startScanning() {
        if (experience != null) {
            Log.i("a", "Start Scanning");
            detector = this.getNewDetector(experience);
            detector.setCallback(new DetectorCallback() {
                @Override
                public void detectionStart(final int margin) {
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Log.i("cameraErrorView", "Getting camera error view...");
                            View errorView = findViewById(R.id.cameraError);
                            if (errorView != null) {
                                Log.i("cameraErrorView", "Setting camera error view to GONE");
                                errorView.setVisibility(View.GONE);
                            }
                            progressBar.setVisibility(View.VISIBLE);
                            if (getResources()
                                    .getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) {
                                View topView = findViewById(R.id.topView);
                                if (topView != null) {
                                    topView.setLayoutParams(new LinearLayout.LayoutParams(
                                            ViewGroup.LayoutParams.MATCH_PARENT, margin));
                                }
                                View bottomView = findViewById(R.id.bottomView);
                                if (bottomView != null) {
                                    bottomView.setLayoutParams(new LinearLayout.LayoutParams(
                                            ViewGroup.LayoutParams.MATCH_PARENT, margin));
                                }
                            } else {
                                View topView = findViewById(R.id.topView);
                                if (topView != null) {
                                    topView.setLayoutParams(new LinearLayout.LayoutParams(margin,
                                            ViewGroup.LayoutParams.MATCH_PARENT));
                                }
                                View bottomView = findViewById(R.id.bottomView);
                                if (bottomView != null) {
                                    bottomView.setLayoutParams(new LinearLayout.LayoutParams(margin,
                                            ViewGroup.LayoutParams.MATCH_PARENT));
                                }
                            }
                        }
                    });
                }
            });
            detector.setOverlay((ImageView) findViewById(R.id.overlay));
            if (getSupportActionBar() != null && experience.getScanScreenTextTitle() == null) {
                getSupportActionBar().setDisplayShowTitleEnabled(true);
                getSupportActionBar().setTitle(experience.getName());
            }
            cameraView.setDetector(detector, experience);

            if (cameraView.deviceNeedsTapToFocus()) {
                // tap to focus
                View v = findViewById(R.id.thumbnailImageLayout);
                if (v != null) {
                    v.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View view) {
                            setFocusTextVisible(false);
                            cameraView.focus(new Runnable() {
                                @Override
                                public void run() {
                                    setFocusTextVisible(true);
                                }
                            });

                        }
                    });
                }
                setFocusTextVisible(true);
            }
        } else {
            cameraView.setDetector(null, null);
        }
    }

    private boolean focusTextAlreadyShown = false;

    private void setFocusTextVisible(final boolean visible) {
        final TextView focusTextView = (TextView) findViewById(R.id.focusText);
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                if (focusTextView != null) {
                    if (focusTextAlreadyShown) {
                        focusTextView.setText(R.string.tap_to_refocus);
                        focusTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18);
                        focusTextView.setGravity(Gravity.TOP | Gravity.CENTER_HORIZONTAL);
                    }
                    if (visible) {
                        focusTextView.setVisibility(View.VISIBLE);
                    } else {
                        focusTextView.setVisibility(View.INVISIBLE);
                        focusTextAlreadyShown = true;
                    }
                }
            }
        });
    }

    private String lastFoundCode = null;

    private void onCodeDetected(final String markerCode) {
        if (experience != null) {
            if (experience.getOpenWithoutUserInput() == null || experience.getOpenWithoutUserInput()) {
                returnCode(markerCode);
            } else if (!markerCode.equals(lastFoundCode)) {
                final Experience experience = getExperience();
                final Action action = experience.getActionForCode(markerCode);
                if (action != null) {
                    lastFoundCode = markerCode;
                    final Button actionButton = (Button) actionView.findViewById(R.id.scan_event_button);
                    if (actionButton != null) {

                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                actionButton.setText(action.getName() != null && !action.getName().equals("")
                                        ? action.getName()
                                        : (action.getDisplayUrl() != null && !action.getDisplayUrl().equals("")
                                                ? action.getDisplayUrl()
                                                : markerCode));
                                actionButton.setOnClickListener(new View.OnClickListener() {
                                    @Override
                                    public void onClick(View v) {
                                        returnCode(markerCode);
                                    }
                                });
                            }
                        });
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                actionAnimator.showView();
                                progressBar.setVisibility(View.INVISIBLE);
                            }
                        });
                    }
                }
            }
        }
    }

    private void returnCode(String markerCode) {
        Log.i("Marker", "MarkerDisplay Detected: " + markerCode);
        if (markerCode != null) {
            if (experience.getCallback() != null) {
                startActivity(new Intent(Intent.ACTION_VIEW,
                        Uri.parse(experience.getCallback().replace("{code}", markerCode))));
            } else {
                Intent intent = getIntent();
                intent.putExtra("marker", markerCode);
                setResult(RESULT_OK, intent);
                finish();
            }
        }
    }

    protected void loadExperience(Bundle savedInstanceState) {
        if (savedInstanceState != null && savedInstanceState.containsKey("experience")) {

            loaded(new Gson().fromJson(savedInstanceState.getString("experience"), Experience.class));
        } else {
            Intent intent = getIntent();
            if (intent.hasExtra("experience")) {
                loaded(new Gson().fromJson(intent.getStringExtra("experience"), Experience.class));
            }
        }
    }

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        loadExperience(savedInstanceState);
    }

    private Drawable getTintedDrawable(@DrawableRes int drawable, @ColorInt int color) {
        final Drawable original = ContextCompat.getDrawable(this, drawable);
        if (original != null) {
            final Drawable wrapDrawable = DrawableCompat.wrap(original);
            DrawableCompat.setTint(wrapDrawable, color);
            return wrapDrawable;
        }
        return null;
    }

    private void createSettingsUI(List<DetectorSetting> settings) {
        settingIcons.removeAllViews();
        if (settings != null && !settings.isEmpty()) {
            final int padding = getResources().getDimensionPixelSize(R.dimen.setting_padding);
            List<DetectorSetting> settingList = settings;
            if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
                settingList = Lists.reverse(settings);
            }
            for (final DetectorSetting setting : settingList) {
                final ImageView button = new ImageView(this);
                button.setContentDescription(getString(setting.getText()));
                final int[] attrs = new int[] { android.R.attr.selectableItemBackground };
                final TypedArray ta = obtainStyledAttributes(attrs);
                final Drawable drawableFromTheme = ta.getDrawable(0);
                ta.recycle();
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                    button.setImageResource(setting.getIcon());
                    button.setImageTintList(ColorStateList.valueOf(Color.WHITE));
                    button.setBackground(drawableFromTheme);
                } else {
                    button.setImageDrawable(getTintedDrawable(setting.getIcon(), Color.WHITE));
                    //noinspection deprecation
                    button.setBackgroundDrawable(drawableFromTheme);
                }

                button.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        setting.nextValue();
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                            button.setImageResource(setting.getIcon());
                        } else {
                            button.setImageDrawable(getTintedDrawable(setting.getIcon(), Color.WHITE));
                        }
                        button.setContentDescription(getString(setting.getText()));
                        textAnimator.setText(setting.getText());
                    }
                });
                final LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
                        LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT, 1);
                params.weight = 1;
                button.setLayoutParams(params);
                settingIcons.addView(button);
                button.setPadding(padding, padding, padding, padding);
            }

        }

        menuAnimator.setViewVisible(settingIcons.getChildCount() > 0);
    }

    protected ArtcodeDetector getNewDetector(Experience experience) {
        return new ArtcodeDetector(this, experience,
                new MarkerCodeDetectionHandler(this.experience, new CodeDetectionHandler() {
                    @Override
                    public void onMarkerCodeDetected(String code) {
                        onCodeDetected(code);
                    }
                }), this.cameraView);
    }
}