com.segma.trim.MainActivity.java Source code

Java tutorial

Introduction

Here is the source code for com.segma.trim.MainActivity.java

Source

package com.segma.trim;

import android.Manifest;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.DialogFragment;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.FileProvider;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.util.Log;
import android.util.TypedValue;
import android.view.Display;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.WindowManager;
import android.view.animation.AlphaAnimation;
import android.view.animation.Animation;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.PopupWindow;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.gms.ads.AdListener;
import com.google.android.gms.ads.AdRequest;
import com.google.android.gms.ads.AdView;
import com.google.android.gms.ads.InterstitialAd;
import com.google.android.gms.ads.MobileAds;
import com.segma.dirchooser.DirectoryChooserConfig;
import com.segma.dirchooser.DirectoryChooserFragment;
import com.segma.trim.InAppBillingUtilities.InAppBillingBroadcastReceiver;
import com.segma.trim.InAppBillingUtilities.InAppBillingHelper;
import com.segma.trim.InAppBillingUtilities.InAppBillingResult;
import com.segma.trim.InAppBillingUtilities.Inventory;
import com.segma.trim.InAppBillingUtilities.Purchase;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

public class MainActivity extends AppCompatActivity implements ActivityCompat.OnRequestPermissionsResultCallback,
        InAppBillingHelper.OnInAppBillingPurchaseFinishedListener,
        InAppBillingBroadcastReceiver.InAppBillingBroadcastListener,
        DirectoryChooserFragment.OnFragmentInteractionListener, ImageProcessingView.SaveTriangulatedBitmapCallback,
        SeekBar.OnSeekBarChangeListener, ColorPickerDialog.OnColorChangedListener,
        InAppBillingHelper.QueryInventoryFinishedListener {

    /**
     * Debug
     */
    private static final String TAG = "trim";
    private static boolean MODE_DEBUG = false;

    /**
     * License
     */
    private static final String PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApxkR5S3wRAWRZY+LDMy0H9y7YfExOdPYovUbEg6h+/hbiIcqh+FfOuLF1YgQy8zOdle58VAv8ATyh6L2+TL+Dtcw7ShXAKpin4lEtjEeSaNGjpYf7EGyQ/TtQzC9IiZ2za21h91/c4iYBVRjv8rzHTl4LDmTydjnoOObB2cvVCvPas1KHfCo31hQA3/a4k7DXfR9yo+FDGf0RWL0Jd9mw7ocfSQAzLXQzJNZA2GMVQvOecEXa4bRpFUdpCziNw6qtFkr7gQFl+T+L/TcoHLvVYJqEcUa9BYOljZo0vQ4r9y7BDEczf7LA19IplRQUuiv1v4aAIfQDGgo3jsGRL6UtwIDAQAB";
    private static final String PURCHASE_KEY = PUBLIC_KEY;
    private static boolean isLicenseLoaded = false;
    private static final boolean LICENSE_PREMIUM = true;
    private static final boolean LICENSE_TRIAL = false;
    private static final String LICENSE_PREMIUM_ID = "product_triango_license_premium_2016_7_16";
    private static boolean LICENSE = LICENSE_TRIAL;
    private static InAppBillingHelper purchaseHelper;
    private static InAppBillingBroadcastReceiver broadcastReceiver;
    private static final int REQUEST_CODE_PURCHASE = 8080;

    /**
     * Admob
     */
    private static final String ADMOB_KEY = "ca-app-pub-3882895524336494~4932860163";

    /**
     * Screen size
     */
    int screenWidth = 0;
    int screenHeight = 0;

    /**
     * Message & State Constants
     */
    private static final String WARNING_NO_APPROPRIATE_INTENT = "No share application found.";
    private static final String MESSAGE_IMAGE_SAVED = "Image is saved.";
    private static final String ERROR_GOOGLE_PLAY_NOT_AVAILABLE = "Google Play is temporarily not available.";
    private static final String WARNING_CAMERA_IMPORT_ERROR = "Error in importing camera image.";
    private static final String WARNING_NO_SDCARD = "No SD card available.";
    private static final String MESSAGE_PURCHASE = "Congratulations! You are premium now. Enjoy!";
    private static final String WARNING_NO_IMAGE_IMPORTED = "No image is imported.";
    private static final String WARNING_PREMIUM_FEATURE_SAVE_IMAGE = "Go premium to save image.";
    private static final String WARNING_PREMIUM_FEATURE_SHARE_IMAGE = "Go premium to share image.";
    private static final String WARNING_COMPUTING = "Already running...";
    private static final String WARNING_SAVE_IMAGE_FAILED = "Failed to save image.\nPlease choose another SD Card.";
    private static final String MESSAGE_STARTUP = "Press me to load a random sample\nor take image from camera or gallery.";
    private static final int STATE_NO_IMAGE_IMPORTED = 1;
    private static final int STATE_PROCESSING_IMAGE = 2;
    private int STATE = STATE_NO_IMAGE_IMPORTED;
    private static final int REQUEST_CODE_SHARE = 9090;

    /**
     * TextView
     */
    public final static int LONG_PRESS_TIME_ON_TEXTVIEW = 500;
    private final Handler handlerOnTextView = new Handler();
    private TextView textView;

    /**
     * ColorPickerDialog
     */
    private ColorPickerDialog colorPickerDialog;

    /**
     * PopupWindow
     */
    PopupWindow popupWindowAbout;

    /**
     * Toolbar
     **/
    private static boolean isMenuLoaded = false;
    private Menu menu;
    private MenuItem menuItem_TakeAPhoto;
    private MenuItem menuItem_ImportFromGallery;
    private ActionBar actionBar;
    private boolean isMenuLocked = false;

    /**
     * ImageView
     */
    private ImageProcessingView ipv;
    private int ImageProcessingViewHeight = 0;
    private int ImageProcessingViewWidth = 0;

    /**
     * External Storage & Share Controls
     */
    private DirectoryChooserFragment dirChooser;
    private static boolean isExternalStorageAllowed = true;
    private static int REQUEST_CODE_EXTERNAL_STORAGE_PERMISSION = 7070;
    private static final int ACTION_SHARE = 3;
    private static final int ACTION_SAVE = 4;
    private static int ACTION = ACTION_SAVE;
    private static Uri shareCacheUri = null;
    private OutputStream out;
    String cacheFileName = "9p845y1034895y9q348hf34hf.jpg";

    /**
     * Algorithm values
     */
    private Bitmap rawBitmap;
    private int rawBitmapWidth;
    private int rawBitmapHeight;
    private boolean IMAGE_ROTATED_TO_PROCESS = false;

    /**
     * Memory
     */
    private static int MEMORY_SIZE = 0;
    private static int MAX_BITMAP_PIXELS = 0;

    /**
     * User Preference
     */
    private static SharedPreferences preferences;
    private static SharedPreferences.Editor preferenceEditor;
    private static final String USER_PREFERENCE = "0";
    // save location
    private static final String PREF_SAVE_LOCATION = "1";
    private static String PREF_SAVE_LOCATION_NULL;
    private static String PREF_SAVE_LOCATION_VALUE;
    // mesh
    private static final String PREF_MESH = "4";
    private static boolean PREF_MESH_NULL = false;
    private static boolean PREF_MESH_VALUE;
    // color
    private static final String PREF_COLOR = "2";
    private static int PREF_COLOR_NULL = Color.parseColor("#99FF00");
    private static int PREF_COLOR_VALUE;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        MobileAds.initialize(getApplicationContext(), ADMOB_KEY);
        setContentView(R.layout.activity_main);
        loadAds();
        MEMORY_SIZE = ((ActivityManager) getSystemService(ACTIVITY_SERVICE)).getMemoryClass();
        MAX_BITMAP_PIXELS = calculateMaxBitmapPixels();
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        ipv = (ImageProcessingView) findViewById(R.id.ipv);
        loadLicense();
        loadUserSetting();
        final Runnable runnableOnTextView = new Runnable() {
            @Override
            public void run() {
                ipv.setVisibility(View.VISIBLE);
                // TODO: update pending: the image enlarges due to larger space
                rawBitmap = getSampleImage();
                rawBitmapWidth = rawBitmap.getWidth();
                rawBitmapHeight = rawBitmap.getHeight();
                STATE = STATE_PROCESSING_IMAGE;
                textView.setVisibility(View.GONE);
                ipv.process(rawBitmap);
            }
        };
        Display display = getWindowManager().getDefaultDisplay();
        Point size = new Point();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR2) {
            display.getSize(size);
            screenWidth = size.x;
            screenHeight = size.y;
        } else {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
            screenWidth = display.getWidth();
            screenHeight = display.getHeight();
        }

        initControls();
        textView = (TextView) findViewById(R.id.tv_message);
        textView.setEnabled(false);
        ViewTreeObserver viewTreeObserver = ipv.getViewTreeObserver();
        if (viewTreeObserver.isAlive()) {
            viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
                @Override
                public void onGlobalLayout() {
                    ImageProcessingViewWidth = ipv.getWidth();
                    ImageProcessingViewHeight = ipv.getHeight();
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                        ipv.getViewTreeObserver().removeOnGlobalLayoutListener(this);
                    } else {
                        ipv.getViewTreeObserver().removeGlobalOnLayoutListener(this);
                    }
                    if (ImageProcessingViewHeight != 0)
                        textView.setEnabled(true);
                }
            });
        }
        textView.setText(MESSAGE_STARTUP);
        textView.setOnTouchListener(new View.OnTouchListener() {
            float original_text_size;

            @Override
            public boolean onTouch(View v, final MotionEvent event) {
                switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    original_text_size = textView.getTextSize();
                    //textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, Math.round(original_text_size * 1.15));
                    handlerOnTextView.postDelayed(runnableOnTextView, LONG_PRESS_TIME_ON_TEXTVIEW);
                    textView.setEnabled(false);
                    break;
                case MotionEvent.ACTION_MOVE:
                    handlerOnTextView.removeCallbacks(runnableOnTextView);
                    break;
                case MotionEvent.ACTION_UP:
                    //textView.setTextSize(TypedValue.COMPLEX_UNIT_PX, original_text_size);
                    handlerOnTextView.removeCallbacks(runnableOnTextView);
                    v.setEnabled(true);
                    break;
                }
                return false;
            }
        });
        setSupportActionBar((Toolbar) findViewById(R.id.toolbar));
        actionBar = getSupportActionBar();
        //actionBar.setDisplayHomeAsUpEnabled(true);
        ipv.setVisibility(View.INVISIBLE);

        if (MODE_DEBUG) {
            LICENSE = LICENSE_PREMIUM;
            getPackageManager().clearPackagePreferredActivities(getApplicationContext().getPackageName());
        }
    }

    private void loadLicense() {
        purchaseHelper = new InAppBillingHelper(this, PUBLIC_KEY);
        purchaseHelper.enableDebugLogging(true);
        purchaseHelper.startSetup(new InAppBillingHelper.OnInAppBillingSetupFinishedListener() {
            @Override
            public void onInAppBillingSetupFinished(InAppBillingResult result) {
                if (!result.isSuccess()) {
                    Log.d(TAG, "InAppBillingHelper setting up failed: " + result);
                    return;
                }
                if (purchaseHelper == null)
                    return;
                broadcastReceiver = new InAppBillingBroadcastReceiver(MainActivity.this);
                registerReceiver(broadcastReceiver, new IntentFilter(InAppBillingBroadcastReceiver.ACTION));

                Log.d(TAG, "Helper setup successful. Querying inventory.");
                try {
                    purchaseHelper.queryInventoryAsync(MainActivity.this);
                } catch (InAppBillingHelper.InAppBillingAsyncInProgressException e) {
                    Log.d(TAG, "Error querying inventory. Another async request is not finished.");
                }
            }
        });
    }

    private void initControls() {
        int MIN_TAG_WIDTH = 20;
        int MIN_VALUE_WIDTH = 10;
        int MIN_GO_WIDTH = 15;
        int TAG_WIDTH = Math.round((float) 0.2 * screenWidth);
        int VALUE_WIDTH = Math.round((float) 0.1 * screenWidth);
        int GO_WIDTH = Math.round((float) 0.15 * screenWidth);
        if (TAG_WIDTH < MIN_TAG_WIDTH)
            TAG_WIDTH = MIN_TAG_WIDTH;
        if (VALUE_WIDTH < MIN_VALUE_WIDTH)
            VALUE_WIDTH = MIN_VALUE_WIDTH;
        if (GO_WIDTH < MIN_GO_WIDTH)
            GO_WIDTH = MIN_GO_WIDTH;

        ((TextView) findViewById(R.id.tv_density_tag)).setWidth(TAG_WIDTH);
        ((TextView) findViewById(R.id.tv_density_value)).setWidth(VALUE_WIDTH);
        ((TextView) findViewById(R.id.tv_density_value)).setText(String.valueOf(density_min));
        ((TextView) findViewById(R.id.tv_complexity_tag)).setWidth(TAG_WIDTH);
        ((TextView) findViewById(R.id.tv_complexity_value)).setWidth(VALUE_WIDTH);
        ((TextView) findViewById(R.id.tv_complexity_value)).setText(String.valueOf(complexity_min));
        ((Button) findViewById(R.id.bt_go)).setWidth(GO_WIDTH);

        int step = 100 / 8;
        ((SeekBar) findViewById(R.id.sb_complexity)).incrementProgressBy(step);
        ((SeekBar) findViewById(R.id.sb_complexity)).setOnSeekBarChangeListener(this);
        ((SeekBar) findViewById(R.id.sb_complexity)).setProgress(2 * step);
        step = Math.round(100 / 7);
        ((SeekBar) findViewById(R.id.sb_density)).setKeyProgressIncrement(step);
        ((SeekBar) findViewById(R.id.sb_density)).setOnSeekBarChangeListener(this);
        ((SeekBar) findViewById(R.id.sb_density)).setProgress(5 * step);

        findViewById(R.id.bt_go).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (ipv.getDrawable() == null) {
                    showWarning(WARNING_NO_IMAGE_IMPORTED);
                    return;
                }
                if (ImageProcessingView.STATUS == ImageProcessingView.STATUS_COMPUTING) {
                    Toast.makeText(getApplicationContext(), WARNING_COMPUTING, Toast.LENGTH_SHORT).show();
                    return;
                }
                ipv.process();
            }
        });

        findViewById(R.id.bt_go).setOnTouchListener(new View.OnTouchListener() {
            float original_size_in_sp = 0;
            boolean o_o = true;

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                case MotionEvent.ACTION_DOWN:
                    if (o_o)
                        original_size_in_sp = pixelsToSp(((Button) v).getTextSize());
                    ((Button) v).setTextSize(TypedValue.COMPLEX_UNIT_SP, Math.round(original_size_in_sp * 0.9));
                    if (o_o)
                        o_o = false;
                    break;
                case MotionEvent.ACTION_UP:
                    ((Button) v).setTextSize(TypedValue.COMPLEX_UNIT_SP, Math.round(original_size_in_sp));
                    ;
                    break;
                }
                return false;
            }
        });
    }

    public float pixelsToSp(float px) {
        float scaledDensity = getResources().getDisplayMetrics().scaledDensity;
        return px / scaledDensity;
    }

    private void loadUserSetting() {
        preferences = getSharedPreferences(USER_PREFERENCE, MODE_PRIVATE);
        preferenceEditor = preferences.edit();
        if (isSDCARDAvailable()) {
            // check phone version > 5.1
            if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) {
                isExternalStorageAllowed = checkPermission_6_0(this);
            }
            PREF_SAVE_LOCATION_NULL = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)
                    .getAbsolutePath();
            PREF_SAVE_LOCATION_VALUE = preferences.getString(PREF_SAVE_LOCATION, PREF_SAVE_LOCATION_NULL);

            Log.d(TAG, "isExternalStorageAllowed: " + String.valueOf(isExternalStorageAllowed));
        } else {
            //Toast.makeText(getApplicationContext(), WARNING_NO_SDCARD, Toast.LENGTH_LONG).show();
            PREF_SAVE_LOCATION_NULL = getFilesDir().getAbsolutePath();
            PREF_SAVE_LOCATION_VALUE = preferences.getString(PREF_SAVE_LOCATION, PREF_SAVE_LOCATION_NULL);
        }

        PREF_COLOR_VALUE = preferences.getInt(PREF_COLOR, PREF_COLOR_NULL);
        ipv.setInkColor(PREF_COLOR_VALUE);

    }

    @Override
    protected void onResume() {
        //TODO: 11-4-2016 FIX: Hiding Navigation Bar seems not permanently, scheme disposed
        //hideNavigationBar();
        super.onResume();
    }

    private void hideNavigationBar() {

        //TODO: 11-4-2016 FIX: Hide Navigation Bar
        final int flags = View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_FULLSCREEN
                //| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
                | View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
        final View decorView = getWindow().getDecorView();
        decorView.setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener() {
            @Override
            public void onSystemUiVisibilityChange(int visibility) {
                // Note that system bars will only be "visible" if none of the
                // LOW_PROFILE, HIDE_NAVIGATION, or FULLSCREEN flags are set.
                if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
                    // TODO: The system bars are visible. Make any desired
                    // adjustments to your UI, such as showing the action bar or
                    // other navigational controls.

                    //decorView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
                    //decorView.setSystemUiVisibility(decorView.getSystemUiVisibility());
                    //getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE);
                    decorView.setSystemUiVisibility(flags);
                    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                            WindowManager.LayoutParams.FLAG_FULLSCREEN);
                } else {
                    // TODO: The system bars are NOT visible. Make any desired
                    // adjustments to your UI, such as hiding the action bar or
                    // other navigational controls.
                }
            }
        });
        decorView.setSystemUiVisibility(flags);
    }

    private int calculateMaxBitmapPixels() {
        float percentageEachBitmapInUse = 0.15f;
        float eachPixelMemory = (float) 8;

        return (int) (percentageEachBitmapInUse * MEMORY_SIZE * 1024 * 1024 / eachPixelMemory);
    }

    private Bitmap getSampleImage() {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        options.inScaled = false;
        int sample = getRandomSample();
        BitmapFactory.decodeResource(getResources(), sample, options);
        int imageHeight = options.outHeight;
        int imageWidth = options.outWidth;

        options.inJustDecodeBounds = false;
        if (true || imageHeight >= ImageProcessingViewHeight || imageWidth >= ImageProcessingViewWidth) {
            options.inSampleSize = calculateInSampleSize(options,
                    ImageProcessingViewHeight * imageWidth / imageHeight, ImageProcessingViewHeight);
            return Bitmap.createScaledBitmap(
                    decodeSampledBitmapFromResource(getResources(), sample,
                            ImageProcessingViewHeight * imageWidth / imageHeight, ImageProcessingViewHeight),
                    ImageProcessingViewHeight * imageWidth / imageHeight, ImageProcessingViewHeight, true);
        }
        return BitmapFactory.decodeResource(getResources(), sample, options);
        //decodeSampledBitmapFromResource(getResources(), R.drawable.sample, ImageProcessingViewHeight * imageWidth / imageHeight, ImageProcessingViewHeight);
    }

    private int getRandomSample() {
        int out_ = getResources().getIdentifier("sample_" + String.valueOf(RandomGenerator.getIntFromRange(1, 4)),
                "drawable", getPackageName());
        return out_;
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.action_buttons, menu);
        this.menu = menu;
        //menuItem_TakeAPhoto = toolbar.getMenu().findItem(R.id.take_a_photo);
        //menuItem_ImportFromGallery = toolbar.getMenu().findItem(R.id.import_from_gallery);
        //toolbar.getMenu().findItem(R.id.about).setVisible(false);
        menu.findItem(R.id.about).setVisible(false);
        menuItem_ImportFromGallery = menu.findItem(R.id.import_from_gallery);
        menuItem_TakeAPhoto = menu.findItem(R.id.take_a_photo);
        isMenuLoaded = true;
        if (isLicenseLoaded && LICENSE)
            menu.findItem(R.id.premium).setVisible(false);

        // load show mesh preference
        PREF_MESH_VALUE = preferences.getBoolean(PREF_MESH, PREF_MESH_NULL);
        if (PREF_MESH_VALUE) {
            menu.findItem(R.id.show_mesh).setTitle(R.string.hide_mesh);
            return super.onCreateOptionsMenu(menu);
        }
        menu.findItem(R.id.show_mesh).setTitle(R.string.show_mesh);
        return super.onCreateOptionsMenu(menu);
    }

    private void updateUI() {
        ipv.hideProgressDialog();
        if (!LICENSE) {
            getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
            return;
        }
        if (LICENSE && isMenuLoaded)
            menu.findItem(R.id.premium).setVisible(false);
    }

    private void showWarning(final String string) {

        //(findViewById(R.id.bt_go)).setEnabled(false);
        //(findViewById(R.id.save_file)).setEnabled(false);
        //textView.setEnabled(false);
        lockScreen();
        final Animation in = new AlphaAnimation(0f, 1f) {
            {
                setDuration(250);
            }
        };
        final Animation out = new AlphaAnimation(1f, 0f) {
            {
                setDuration(250);
            }
        };
        out.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
            }

            @Override
            public void onAnimationEnd(Animation animation) {
                textView.setText(string);
                textView.startAnimation(in);
            }

            @Override
            public void onAnimationRepeat(Animation animation) {
            }
        });
        in.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {
                if (!textView.getText().toString().equals(WARNING_NO_IMAGE_IMPORTED)) {
                    //textView.setEnabled(true);
                    //(findViewById(R.id.bt_go)).setEnabled(true);
                    //(findViewById(R.id.save_file)).setEnabled(true);
                    unlockScreen();
                }
            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }
        });

        textView.startAnimation(out);
        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                out.setAnimationListener(new Animation.AnimationListener() {
                    @Override
                    public void onAnimationStart(Animation animation) {
                    }

                    @Override
                    public void onAnimationEnd(Animation animation) {
                        textView.setText(MESSAGE_STARTUP);
                        textView.startAnimation(in);
                    }

                    @Override
                    public void onAnimationRepeat(Animation animation) {
                    }
                });
                textView.startAnimation(out);
            }
        }, 1500);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if (isMenuLocked)
            return super.onOptionsItemSelected(item);
        ipv.setClickable(false);
        switch (STATE) {
        case STATE_NO_IMAGE_IMPORTED:
            switch (item.getItemId()) {
            case R.id.online_gallery:
                goOnlineGallery();
                return super.onOptionsItemSelected(item);
            case R.id.premium:
                goPremium();
                return super.onOptionsItemSelected(item);
            case R.id.take_a_photo:
                photoFromCamera();
                return super.onOptionsItemSelected(item);
            case R.id.import_from_gallery:
                importFromGallery();
                return super.onOptionsItemSelected(item);
            case R.id.save_file:
                showWarning(WARNING_NO_IMAGE_IMPORTED);
                return super.onOptionsItemSelected(item);
            case R.id.show_mesh:
                showWarning(WARNING_NO_IMAGE_IMPORTED);
                return super.onOptionsItemSelected(item);
            case R.id.save_location:
                if (LICENSE == LICENSE_TRIAL) {
                    Toast.makeText(getApplicationContext(), WARNING_PREMIUM_FEATURE_SAVE_IMAGE, Toast.LENGTH_SHORT)
                            .show();
                    return super.onOptionsItemSelected(item);
                }
                showSaveLocation();
                return super.onOptionsItemSelected(item);
            case R.id.meshColor:
                showWarning(WARNING_NO_IMAGE_IMPORTED);
                return super.onOptionsItemSelected(item);
            case R.id.share:
                showWarning(WARNING_NO_IMAGE_IMPORTED);
                return super.onOptionsItemSelected(item);
            case R.id.about:
                showAbout();
                return super.onOptionsItemSelected(item);
            //TODO: 11-4-2016 FIX: Hiding Navigation Bar scheme dispose, exit button not required
            /*
            case R.id.exit:
                exit();
                return super.onOptionsItemSelected(item);
                */
            default:
                return super.onOptionsItemSelected(item);
            }
        case STATE_PROCESSING_IMAGE:
            switch (item.getItemId()) {
            case R.id.online_gallery:
                goOnlineGallery();
                return super.onOptionsItemSelected(item);
            case R.id.premium:
                goPremium();
                return super.onOptionsItemSelected(item);
            case R.id.take_a_photo:
                photoFromCamera();
                return super.onOptionsItemSelected(item);
            case R.id.import_from_gallery:
                importFromGallery();
                return super.onOptionsItemSelected(item);
            case R.id.save_file:
                if (LICENSE == LICENSE_TRIAL) {
                    Toast.makeText(getApplicationContext(), WARNING_PREMIUM_FEATURE_SAVE_IMAGE, Toast.LENGTH_SHORT)
                            .show();
                    return super.onOptionsItemSelected(item);
                }
                requestProcessedPhoto();
                return super.onOptionsItemSelected(item);
            case R.id.show_mesh:
                if (!ipv.SHOW_MESH) {
                    item.setTitle(R.string.hide_mesh);
                    ipv.showMesh(true);
                    PREF_MESH_VALUE = true;
                    preferenceEditor.putBoolean(PREF_MESH, PREF_MESH_VALUE);
                    preferenceEditor.commit();
                } else {
                    item.setTitle(R.string.show_mesh);
                    ipv.showMesh(false);
                    PREF_MESH_VALUE = false;
                    preferenceEditor.putBoolean(PREF_MESH, PREF_MESH_VALUE);
                    preferenceEditor.commit();
                }
                return super.onOptionsItemSelected(item);
            case R.id.meshColor:
                showColorPickerDialog();
                return super.onOptionsItemSelected(item);
            case R.id.save_location:
                if (LICENSE == LICENSE_TRIAL) {
                    Toast.makeText(getApplicationContext(), WARNING_PREMIUM_FEATURE_SAVE_IMAGE, Toast.LENGTH_SHORT)
                            .show();
                    return super.onOptionsItemSelected(item);
                }
                showSaveLocation();
                return super.onOptionsItemSelected(item);
            case R.id.share:
                /*
                if (LICENSE == LICENSE_TRIAL) {
                    Toast.makeText(getApplicationContext(), WARNING_PREMIUM_FEATURE_SHARE_IMAGE, Toast.LENGTH_SHORT).show();
                    return super.onOptionsItemSelected(item);
                }
                */
                share();
                return super.onOptionsItemSelected(item);
            case R.id.about:
                showAbout();
                return super.onOptionsItemSelected(item);
            //TODO: 11-4-2016 FIX: Hiding Navigation Bar scheme dispose, exit button not required
            /*
            case R.id.exit:
                exit();
                return super.onOptionsItemSelected(item);
                */
            default:
                return super.onOptionsItemSelected(item);
            }
        }
        ipv.setClickable(true);
        return super.onOptionsItemSelected(item);
    }

    private void goOnlineGallery() {
        Toast.makeText(getApplicationContext(), "Online gallery will be avaliable soon.", Toast.LENGTH_LONG).show();
    }

    private void share() {
        Log.d(TAG, "Sharing photo.");
        if (isMenuLoaded) {
            ACTION = ACTION_SHARE;
            requestProcessedPhoto();
        }
    }

    private void goPremium() {
        try {
            ipv.showProgressDialog();
            if (purchaseHelper == null || !isLicenseLoaded) {
                Toast.makeText(getApplicationContext(), ERROR_GOOGLE_PLAY_NOT_AVAILABLE, Toast.LENGTH_LONG).show();
                ipv.hideProgressDialog();
                return;
            }
            purchaseHelper.launchPurchaseFlow(this, LICENSE_PREMIUM_ID, REQUEST_CODE_PURCHASE, MainActivity.this,
                    PURCHASE_KEY);
        } catch (InAppBillingHelper.InAppBillingAsyncInProgressException e) {
            ipv.hideProgressDialog();
            Log.d(TAG, "Error launching purchase flow. Another async operation in progress.");
            e.printStackTrace();
        }
    }

    private void showColorPickerDialog() {
        if (colorPickerDialog == null) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                colorPickerDialog = new ColorPickerDialog(this, this, PREF_COLOR_VALUE,
                        (int) (ImageProcessingViewHeight * 0.15), (int) (ImageProcessingViewHeight * 0.1),
                        actionBar.getHeight() / 2, R.style.ColorPickerTheme_v21);
            } else {
                colorPickerDialog = new ColorPickerDialog(this, this, PREF_COLOR_VALUE,
                        (int) (ImageProcessingViewHeight * 0.15), (int) (ImageProcessingViewHeight * 0.1),
                        actionBar.getHeight() / 2, R.style.ColorPickerTheme);
            }
        }
        ipv.setInkColor(PREF_COLOR_VALUE);
        //Log.d("debugging", String.valueOf(actionBar.getHeight()));
        colorPickerDialog.show();
    }

    private void exit() {
        //System.exit(0);
        Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.addCategory(Intent.CATEGORY_HOME);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
    }

    private static final int REQUEST_CODE_GALLERY = 1;
    private static final int REQUEST_CODE_CAMERA = 2;

    private void importFromGallery() {
        startActivityForResult(
                new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI),
                REQUEST_CODE_GALLERY);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        ipv.hideProgressDialog();
        switch (requestCode) {
        case REQUEST_CODE_SHARE:
            // delete cache
            deleteCache();
            unlockMenu();
            unlockScreen();
            ipv.hideProgressDialog();
            try {
                out.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            break;
        case REQUEST_CODE_CAMERA:
            if (resultCode != RESULT_OK) {
                Toast.makeText(getApplicationContext(), WARNING_NO_IMAGE_IMPORTED, Toast.LENGTH_LONG).show();
                return;
            }
            ipv.setVisibility(View.VISIBLE);
            textView.setVisibility(View.INVISIBLE);

            rawBitmap = getBitmapFromPath();
            rawBitmapWidth = rawBitmap.getWidth();
            rawBitmapHeight = rawBitmap.getHeight();

            /*
            if ((float) rawBitmapWidth / rawBitmapHeight < (float) ImageProcessingViewWidth / ImageProcessingViewHeight) {
                IMAGE_ROTATED_TO_PROCESS = true;
                Matrix matrix = new Matrix();
                matrix.postRotate(90);
                rawBitmap = Bitmap.createBitmap(rawBitmap, 0, 0, rawBitmapWidth, rawBitmapHeight, matrix, true);
                Toast.makeText(getApplicationContext(), "Processed image will be rotated back when save.", Toast.LENGTH_LONG).show();
            }
            */

            if (rawBitmap == null) {
                Toast.makeText(getApplicationContext(), WARNING_NO_IMAGE_IMPORTED, Toast.LENGTH_LONG).show();
                break;
            } else {
                ipv.setVisibility(View.VISIBLE);
                textView.setVisibility(View.INVISIBLE);
            }
            ipv.process(compressImgSize2FitIPV(rawBitmap));
            STATE = STATE_PROCESSING_IMAGE;
            break;
        case REQUEST_CODE_GALLERY:
            if (resultCode != RESULT_OK) {
                Toast.makeText(getApplicationContext(), WARNING_NO_IMAGE_IMPORTED, Toast.LENGTH_LONG).show();
                return;
            }
            InputStream stream;
            try {
                stream = getContentResolver().openInputStream(data.getData());
                ipv.setVisibility(View.VISIBLE);
                textView.setVisibility(View.INVISIBLE);

                // FIXME: first calculate suitable size and then ensure import .png format
                rawBitmap = BitmapFactory.decodeStream(stream);
                rawBitmapWidth = rawBitmap.getWidth();
                rawBitmapHeight = rawBitmap.getHeight();
                ipv.process(compressImgSize2FitIPV(rawBitmap));
                STATE = STATE_PROCESSING_IMAGE;
                stream.close();
            } catch (FileNotFoundException e) {
                Toast.makeText(getApplicationContext(), WARNING_NO_IMAGE_IMPORTED, Toast.LENGTH_LONG).show();
                e.printStackTrace();
                break;
            } catch (IOException e) {
                e.printStackTrace();
            }
            break;
        case REQUEST_CODE_PURCHASE:
            if (purchaseHelper == null)
                return;
            if (!purchaseHelper.handleActivityResult(REQUEST_CODE_PURCHASE, resultCode, data)) {
                super.onActivityResult(requestCode, resultCode, data);
            }
            Log.d(TAG, "Request result is processing");
            break;

        }
    }

    private void photoFromCamera() {
        Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
        // Ensure that there's a camera activity to handle the intent
        if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
            // Create the File where the photo should go
            File photoFile = null;
            try {
                photoFile = createImageFile();
            } catch (IOException ex) {
                // Error occurred while creating the File
                Toast.makeText(getApplicationContext(), WARNING_CAMERA_IMPORT_ERROR, Toast.LENGTH_LONG).show();
            }
            // Continue only if the File was successfully created
            if (photoFile != null) {
                takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photoFile));
                startActivityForResult(takePictureIntent, REQUEST_CODE_CAMERA);
            }
        }
    }

    private final static int SAVE_BITMAP_MAX_PIXEL_SIZE = 2400 * 1600;

    private Bitmap getBitmapFromPath() {
        //BitmapFactory.Options bmOptions = new BitmapFactory.Options();
        //bmOptions.inJustDecodeBounds = false;
        // TODO: UPDATE: Decode bitmap to suitable size to avoid memory issue
        BitmapFactory.Options option = new BitmapFactory.Options();
        option.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(mCurrentPhotoPath, option);
        double resizeRatio = Math.sqrt((double) SAVE_BITMAP_MAX_PIXEL_SIZE / (option.outWidth * option.outHeight));
        int autoHeight = (int) (resizeRatio * option.outHeight);
        int autoWidth = (int) (resizeRatio * option.outWidth);
        // Calculate inSampleSize
        option.inSampleSize = calculateInSampleSize(option, autoWidth, autoHeight);
        // Decode bitmap with inSampleSize set
        option.inJustDecodeBounds = false;
        return Bitmap.createScaledBitmap(BitmapFactory.decodeFile(mCurrentPhotoPath, option),
                (int) (resizeRatio * option.outWidth), (int) (resizeRatio * option.outHeight), false);
    }

    private String mCurrentPhotoPath;

    private File createImageFile() throws IOException {
        // Create an image file name
        String imageFileName = "TEMP";
        File storageDir = getExternalFilesDir(null);
        File image = new File(storageDir, imageFileName + ".jpg");

        // Save a file: path for use with ACTION_VIEW intents
        mCurrentPhotoPath = image.getAbsolutePath();
        return image;
    }

    private Bitmap compressImgSize2FitIPV(Bitmap bitmap) {
        int imageHeight = bitmap.getHeight();
        int imageWidth = bitmap.getWidth();

        // TODO: prevent height or width == 0 even after getting bitmap
        while (ImageProcessingViewHeight == 0)
            ;
        return Bitmap.createScaledBitmap(bitmap, ImageProcessingViewHeight * imageWidth / imageHeight,
                ImageProcessingViewHeight, true);

    }

    private void showSaveLocation() {
        if (true || dirChooser == null) {
            dirChooser = DirectoryChooserFragment
                    .newInstance(
                            DirectoryChooserConfig.builder().initialDirectory(PREF_SAVE_LOCATION_VALUE)
                                    .allowReadOnlyDirectory(false).allowNewDirectoryNameModification(true)
                                    .newDirectoryName(getApplicationContext()
                                            .getString(getApplicationContext().getApplicationInfo().labelRes))
                                    .build());

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                dirChooser.setStyle(DialogFragment.STYLE_NO_TITLE, R.style.AppTheme_DialogTheme_API21);
            } else {
                dirChooser.setStyle(DialogFragment.STYLE_NO_TITLE, R.style.AppTheme_DialogTheme);
            }
            //dirChooser.setStyle(DialogFragment.STYLE_NO_TITLE, R.style.AppTheme_DialogTheme);
        }
        dirChooser.show(getFragmentManager(), null);
    }

    private void showAbout() {
        final View view = ((LayoutInflater) getBaseContext().getSystemService(LAYOUT_INFLATER_SERVICE))
                .inflate(R.layout.popup_about, null);

        if (popupWindowAbout == null) {
            float height = ((ImageView) view.findViewById(R.id.imv)).getDrawable().getIntrinsicHeight();
            float width = ((ImageView) view.findViewById(R.id.imv)).getDrawable().getIntrinsicWidth();
            float ratio = height / (2 * width);
            width = Math.round(screenWidth * 0.9f);
            height = width * ratio;
            popupWindowAbout = new PopupWindow(view, Math.round(width), Math.round(height), true);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.CUPCAKE) {
                popupWindowAbout.setOutsideTouchable(true);
            } else {
                popupWindowAbout.setTouchInterceptor(new View.OnTouchListener() {
                    @Override
                    public boolean onTouch(View v, MotionEvent event) {
                        popupWindowAbout.dismiss();
                        return false;
                    }
                });
            }
            popupWindowAbout.setBackgroundDrawable(new BitmapDrawable());
            popupWindowAbout.setAnimationStyle(R.style.AnimationFade);
            //((TextView) view.findViewById(R.id.about_values)).setLinksClickable(true);
            //((TextView) view.findViewById(R.id.about_values)).setTextIsSelectable(false);
            view.setFocusable(true);
            view.setSelected(false);
            //((TextView) view.findViewById(R.id.about_values)).setText(Html.fromHtml("&#160;&#160;&#160;&#160;&#160; Developer: Edward Yung <p> &#160;&#160;&#160;&#160;&#160; Github: <a href='https://github.com/Edward-Yung'>github.com/Edward-Yung</a>"));
            //((TextView) view.findViewById(R.id.about_values)).setMovementMethod(LinkMovementMethod.getInstance());
        }

        popupWindowAbout.showAtLocation(view, Gravity.CENTER, 0, -findViewById(R.id.tv_density_tag).getHeight());
    }

    @Override
    public void onSelectDirectory(String location) {

        // debug
        Log.d(TAG, "isRemovableSDCARDAvaliable: " + String.valueOf(isRemovableSDCARDAvaliable()));
        Log.d(TAG, location);
        Log.d(TAG,
                "getRemovableStorage().getPath(): " + getRemovableStorage() == null
                        ? getRemovableStorage().getPath()
                        : "");
        Log.d(TAG, "isOnRemovableSDCARDPath(location): " + String.valueOf(isOnRemovableSDCARDPath(location)));

        PREF_SAVE_LOCATION_VALUE = location;
        preferenceEditor.putString(PREF_SAVE_LOCATION, PREF_SAVE_LOCATION_VALUE);
        preferenceEditor.commit();
        dirChooser.dismiss();
    }

    @Override
    public void onCancelChooser() {
        dirChooser.dismiss();
    }

    private static int calculateInSampleSize(BitmapFactory.Options options, int reqWidth, int reqHeight) {
        // Raw height and width of image
        final int height = options.outHeight;
        final int width = options.outWidth;
        int inSampleSize = 1;
        if (height > reqHeight || width > reqWidth) {
            final int halfHeight = height / 2;
            final int halfWidth = width / 2;
            // Calculate the largest inSampleSize value that is a power of 2 and keeps both
            // height and width larger than the requested height and width.
            while ((halfHeight / inSampleSize) > reqHeight && (halfWidth / inSampleSize) > reqWidth) {
                inSampleSize *= 2;
            }
        }

        return inSampleSize;
    }

    private static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) {
        // First decode with inJustDecodeBounds=true to check dimensions
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeResource(res, resId, options);
        // Calculate inSampleSize
        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight);
        // Decode bitmap with inSampleSize set
        options.inJustDecodeBounds = false;
        return BitmapFactory.decodeResource(res, resId, options);
    }

    @Override
    public void onProcessedResult(Bitmap bitmap) {
        switch (ACTION) {
        case ACTION_SHARE:
            try {
                File cacheDirectory = new File(getApplicationContext().getCacheDir().getPath() + "/images/");
                cacheDirectory.mkdirs();
                shareCacheUri = Uri
                        .parse(getApplicationContext().getCacheDir().getPath() + "/images/" + cacheFileName);
                // save to cache
                out = new FileOutputStream(shareCacheUri.getPath());
                bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
                File file = new File(shareCacheUri.getPath());
                shareCacheUri = FileProvider.getUriForFile(getApplicationContext(), "com.segma.trim.fileprovider",
                        file);

                // share CacheUri
                Intent send = ImageAPIParser.parse(this, getPackageManager(), shareCacheUri);
                if (send == null) {
                    Toast.makeText(getApplicationContext(), WARNING_NO_APPROPRIATE_INTENT, Toast.LENGTH_LONG)
                            .show();
                    break;
                }
                startActivityForResult(send, REQUEST_CODE_SHARE);

            } catch (Exception e) {
                Log.d(TAG, "Exception: " + e.toString());
                unlockMenu();
                unlockScreen();
                ipv.hideProgressDialog();
                e.printStackTrace();
            }
            ACTION = ACTION_SAVE;
            break;
        case ACTION_SAVE:
            //FIXME: UPDATE PENDING: custom saving location
            try {
                if (isOnRemovableSDCARDPath(PREF_SAVE_LOCATION_VALUE)) {
                    MediaFile mediaFile = new MediaFile(getContentResolver(), new File(PREF_SAVE_LOCATION_VALUE
                            + "/result_" + new SimpleDateFormat("yyyyMMddHHmm").format(new Date()) + ".png"));
                    out = mediaFile.write();
                    bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
                    Toast.makeText(getApplicationContext(), MESSAGE_IMAGE_SAVED, Toast.LENGTH_LONG).show();
                    new Handler().postDelayed(new Runnable() {
                        @Override
                        public void run() {
                            unlockMenu();
                            unlockScreen();
                            ipv.hideProgressDialog();
                        }
                    }, 2000);
                    out.close();
                    break;
                }

                out = new FileOutputStream(PREF_SAVE_LOCATION_VALUE + "/result_"
                        + new SimpleDateFormat("yyyyMMddHHmm").format(new Date()) + ".png");
                bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
                Toast.makeText(getApplicationContext(), MESSAGE_IMAGE_SAVED, Toast.LENGTH_LONG).show();
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        unlockMenu();
                        unlockScreen();
                        ipv.hideProgressDialog();
                    }
                }, 2000);
                out.close();
            } catch (Exception e) {
                unlockMenu();
                unlockScreen();
                ipv.hideProgressDialog();
                Toast.makeText(getApplicationContext(), WARNING_SAVE_IMAGE_FAILED, Toast.LENGTH_LONG).show();
                new Handler().postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        showSaveLocation();
                    }
                }, 1000);
                e.printStackTrace();
            }
            break;
        }
    }

    private void lockScreen() {
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
                WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
    }

    private void unlockScreen() {
        getWindow().clearFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
    }

    private void lockMenu() {
        isMenuLocked = true;
    }

    private void unlockMenu() {
        isMenuLocked = false;
    }

    private void requestProcessedPhoto() {
        Log.d(TAG, "requesting processing results");
        switch (ACTION) {
        case ACTION_SAVE:
            if (isExternalStorageAllowed) {
                lockScreen();
                lockMenu();
                //if (Environment.getExternalStorageState() == Environment.) {
                //Toast.makeText(getApplicationContext(), "Saving image.", Toast.LENGTH_SHORT).show();
                ipv.showProgressDialog();
                ipv.saveTriangulatedImage(this, rawBitmapWidth, rawBitmapHeight);
            } else {
                unlockMenu();
                unlockScreen();
                isExternalStorageAllowed = checkPermission_6_0(this);
                if (!isExternalStorageAllowed) {
                    Toast.makeText(getApplicationContext(), WARNING_SAVE_IMAGE_FAILED, Toast.LENGTH_SHORT).show();
                    return;
                }
                requestProcessedPhoto();
            }
            break;
        case ACTION_SHARE:
            lockScreen();
            lockMenu();
            ipv.showProgressDialog();
            ipv.saveTriangulatedImage(this, rawBitmapWidth, rawBitmapHeight);
            break;
        }
    }

    /**
     * SeekBar's controls
     */
    int complexity_min = 2;
    int complexity_max = 10;
    int complexity = complexity_min;
    float density_min = 0.05f;
    float density_max = 0.95f;
    float density = density_min;
    DecimalFormat df = new DecimalFormat("#.#");

    @Override
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
        switch (seekBar.getId()) {
        case R.id.sb_complexity:
            int richness = (complexity_max - complexity_min) * progress / 100 + complexity_min;
            if (richness == this.complexity)
                break;
            this.complexity = richness;
            ((TextView) findViewById(R.id.tv_complexity_value)).setText(String.valueOf(richness));
            break;
        case R.id.sb_density:
            float density = (density_max - density_min) * progress / 100 + density_min;
            if (density == this.density)
                break;
            this.density = density;
            ((TextView) findViewById(R.id.tv_density_value)).setText(String.valueOf(df.format(density)));
            break;
        }
    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {
        switch (seekBar.getId()) {
        case R.id.sb_complexity:
            //((TextView)findViewById(R.id.tv_richness_value)).setTextColor(getResources().getColor(R.color.BurlyWood));
            //((TextView) findViewById(R.id.tv_richness_value)).setTextSize(18);
            break;
        case R.id.sb_density:
            //((TextView)findViewById(R.id.tv_density_value)).setTextColor(getResources().getColor(R.color.Gray));
            //((TextView) findViewById(R.id.tv_density_value)).setTextSize(18);
            break;
        }
    }

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {
        switch (seekBar.getId()) {
        case R.id.sb_complexity:
            ((TextView) findViewById(R.id.tv_complexity_value))
                    .setTextColor(getResources().getColor(R.color.WhiteSmoke));
            //((TextView) findViewById(R.id.tv_richness_value)).setTextSize(12);
            Log.d(TAG, "java complexity: " + String.valueOf(complexity));
            ImageProcessingView.params.richness = complexity;
            break;
        case R.id.sb_density:
            ((TextView) findViewById(R.id.tv_density_value))
                    .setTextColor(getResources().getColor(R.color.WhiteSmoke));
            //((TextView) findViewById(R.id.tv_density_value)).setTextSize(12);
            Log.d(TAG, "java density: " + String.valueOf(density));
            ImageProcessingView.params.density = density;
            break;
        }
    }

    /**
     * ColorPicker's controls
     */

    @Override
    public void colorChanged(int color) {
        ipv.setInkColor(color);
        PREF_COLOR_VALUE = color;
        preferenceEditor.putInt(PREF_COLOR, PREF_COLOR_VALUE);
        preferenceEditor.commit();
        colorPickerDialog.dismiss();

    }

    /**
     * License
     */
    @Override
    public void receivedBroadcast() {
        try {
            purchaseHelper.queryInventoryAsync(MainActivity.this);
        } catch (InAppBillingHelper.InAppBillingAsyncInProgressException e) {
            Log.d(TAG, "Error querying inventory. Another async request is not finished.");
            e.printStackTrace();
        }
    }

    @Override
    public void onQueryInventoryFinished(InAppBillingResult result, Inventory inventory) {
        Log.d(TAG, "Query inventory finished.");
        if (purchaseHelper == null)
            return;
        if (result.isFailure()) {
            Log.d(TAG, "Failed to query inventory: " + result);
            return;
        }
        Log.d(TAG, "Query inventory was successful.");
        // check license updates
        Purchase purchase = inventory.getPurchase(LICENSE_PREMIUM_ID);
        LICENSE = (purchase != null && isPurchaseLegal(purchase));
        if (MODE_DEBUG) {
            LICENSE = LICENSE_PREMIUM;
            getPackageManager().clearPackagePreferredActivities(getApplicationContext().getPackageName());
        }
        isLicenseLoaded = true;
        updateUI();
    }

    @Override
    public void onInAppBillingPurchaseFinished(InAppBillingResult result, Purchase purchase) {
        Log.d(TAG, "Purchase finished: " + result + ", purchase: " + purchase);
        if (purchaseHelper == null)
            return;
        if (result.isFailure()) {
            Log.d(TAG, "Error purchasing: " + result);
            ipv.hideProgressDialog();
            return;
        }
        if (!isPurchaseLegal(purchase)) {
            Log.d(TAG, "Error purchasing. Authenticity verification failed.");
            ipv.hideProgressDialog();
            return;
        }
        if (purchase.getStockKeepingUnit().equals(LICENSE_PREMIUM_ID)) {
            Log.d(TAG, "Purchase successful.");
            LICENSE = LICENSE_PREMIUM;
            Toast.makeText(getApplicationContext(), MESSAGE_PURCHASE, Toast.LENGTH_LONG).show();
            updateUI();
        } else {
            Log.d(TAG, "Unknown purchase.");
        }
    }

    boolean isPurchaseLegal(Purchase purchase) {
        String purchaseKey = purchase.getDeveloperPayload();
        if (purchaseKey == PURCHASE_KEY)
            return true;
        return false;
    }

    /**
     * Activity Cycles
     */
    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (broadcastReceiver != null) {
            unregisterReceiver(broadcastReceiver);
        }
        if (purchaseHelper != null) {
            purchaseHelper.disposeWhenFinished();
            purchaseHelper = null;
        }
        Log.d(TAG, "Activity is destroyed");
    }

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

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        Log.d(TAG, "activity is request to save states");
        super.onSaveInstanceState(outState);
    }

    /**
     * External Storage functions
     */
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
            @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_CODE_EXTERNAL_STORAGE_PERMISSION)
            isExternalStorageAllowed = (grantResults[0] == PackageManager.PERMISSION_GRANTED);
    }

    private static boolean isSDCARDAvailable() {
        return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
    }

    private static boolean isRemovableSDCARDAvaliable() {
        final String value = System.getenv("SECONDARY_STORAGE");
        if (!TextUtils.isEmpty(value))
            return true;
        return false;
    }

    public static File getRemovableStorage() {
        final String value = System.getenv("SECONDARY_STORAGE");
        if (!TextUtils.isEmpty(value)) {
            final String[] paths = value.split(":");
            for (String path : paths) {
                File file = new File(path);
                if (file.isDirectory()) {
                    return file;
                }
            }
        }
        return null;
    }

    private static boolean isOnRemovableSDCARDPath(String location) {
        final File microSD = getRemovableStorage();
        if (microSD != null) {
            if (("/storage" + location).startsWith(microSD.getAbsolutePath())) {
                return true;
            }
        }
        return false;
    }

    private static boolean checkPermission_6_0(Activity activity) {
        if (ActivityCompat.checkSelfPermission(activity,
                Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)
            return true;
        ActivityCompat.requestPermissions(activity, new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE },
                REQUEST_CODE_EXTERNAL_STORAGE_PERMISSION);
        return false;
    }

    public void deleteCache() {
        try {
            File dir = getCacheDir();
            deleteDir(dir);
        } catch (Exception e) {
        }
    }

    public static boolean deleteDir(File dir) {
        if (dir != null && dir.isDirectory()) {
            String[] children = dir.list();
            for (int i = 0; i < children.length; i++) {
                boolean success = deleteDir(new File(dir, children[i]));
                if (!success) {
                    return false;
                }
            }
            return dir.delete();
        } else if (dir != null && dir.isFile()) {
            return dir.delete();
        } else {
            return false;
        }
    }

    /**
     * Admob
     */
    private static AdView mAdView;
    private static InterstitialAd fullScreenAdView;
    private static int adViewHeight;

    private void loadAds() {
        RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) findViewById(R.id.adView_wrapper)
                .getLayoutParams();
        adViewHeight = params.height;
        params.height = 0;
        findViewById(R.id.adView_wrapper).setLayoutParams(params);
        new Runnable() {
            final Handler handler = new Handler();

            @Override
            public void run() {
                if (!isLicenseLoaded) {
                    handler.postDelayed(this, 1000);
                    return;
                }
                if (LICENSE) {
                    mAdView = (AdView) findViewById(R.id.adView);
                    mAdView.setVisibility(View.GONE);
                    return;
                }
                RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) findViewById(R.id.adView_wrapper)
                        .getLayoutParams();
                params.height = adViewHeight;
                findViewById(R.id.adView_wrapper).setLayoutParams(params);
                //findViewById(R.id.adView_wrapper).setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,RelativeLayout.LayoutParams.WRAP_CONTENT));
                mAdView = (AdView) findViewById(R.id.adView);
                AdRequest adRequest_0 = new AdRequest.Builder().build();
                if (mAdView != null)
                    mAdView.loadAd(adRequest_0);
                fullScreenAdView = new InterstitialAd(MainActivity.this);
                fullScreenAdView.setAdUnitId(getString(R.string.ads_segma_triango_1));
                AdRequest adRequest_1 = new AdRequest.Builder().build();
                if (fullScreenAdView != null)
                    fullScreenAdView.loadAd(adRequest_1);
                fullScreenAdView.setAdListener(new AdListener() {
                    @Override
                    public void onAdClosed() {
                        super.onAdClosed();
                    }

                    @Override
                    public void onAdLoaded() {
                        //showFullScreenAd();
                    }
                });
            }
        }.run();
    }

    public static void showFullScreenAd() {
        if (!isLicenseLoaded || LICENSE)
            return;
        if (fullScreenAdView.isLoaded()) {
            fullScreenAdView.show();
        }
    }

}