com.stillnojetpacks.huffr.activities.MainActivity.java Source code

Java tutorial

Introduction

Here is the source code for com.stillnojetpacks.huffr.activities.MainActivity.java

Source

/**
 * Copyright 2015 Bob Zabor
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License.
 *
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */
package com.stillnojetpacks.huffr.activities;

import android.annotation.TargetApi;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.media.AudioAttributes;
import android.media.AudioManager;
import android.media.SoundPool;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.ShareActionProvider;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageView;

import com.stillnojetpacks.huffr.R;

import java.util.HashMap;
import java.util.Map;
import java.util.Random;

public class MainActivity extends AppCompatActivity
        implements SensorEventListener, SoundPool.OnLoadCompleteListener {

    public static final String TAG = "MainActivity";
    public static final int SOUND_FILE_COUNT = 8; // arbitrary MAX of 8

    private static final String KEY_PREF_SOUNDPOOL_MAX_STREAMS = "soundpoolMaxStreams";
    private static final String KEY_PREF_USE_ALTERNATE_VERTICAL_SOUNDS = "useAlternateVerticalSounds";
    private static final String KEY_PREF_X_HORIZONTAL_SENSITIVITY_THRESHOLD = "xHorizontalSensitivityThreshold";
    private static final String KEY_PREF_Y_VERTICAL_SENSITIVITY_THRESHOLD = "yVerticalSensitivityThreshold";

    private int PREF_SOUNDPOOL_MAX_STREAMS;
    private boolean PREF_USE_ALTERNATE_VERTICAL_SOUNDS;
    private float PREF_X_HORIZONTAL_SENSITIVITY_THRESHOLD;
    private float PREF_Y_VERTICAL_SENSITIVITY_THRESHOLD;

    private ImageView sprayButton;

    private SoundPool soundPool;

    private int sprayStreamId;
    private int capOffSoundId;
    private int spraySoundid;
    private int[] shakeVerticalSoundIds = new int[SOUND_FILE_COUNT];
    private int[] shakeHorizontalSoundIds = new int[SOUND_FILE_COUNT];
    private Map<Integer, Boolean> loaded = new HashMap<>();

    private float lastX, lastY;
    private boolean sensorsInitialized;
    private SensorManager sensorManager;

    private Random random = new Random();

    private ShareActionProvider shareActionProvider;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        setVolumeControlStream(AudioManager.STREAM_MUSIC);

        initializeToolbar();

        initializeSprayButton();

        sensorsInitialized = false;
    }

    @Override
    protected void onStart() {
        super.onStart();
        loadPreferences();
        initializeSoundPool();
        loadSoundResources();
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (sensorManager != null) {
            sensorManager.unregisterListener(this);
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.menu_main, menu);
        MenuItem item = menu.findItem(R.id.action_share_app);

        shareActionProvider = (ShareActionProvider) MenuItemCompat.getActionProvider(item);

        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();

        if (id == R.id.action_share_app) {
            share();
            return true;
        } else if (id == R.id.action_rate_app) {
            rateApp();
            return true;
        } else if (id == R.id.action_settings) {
            startActivity(new Intent(this, SettingsActivity.class));
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    @Override
    public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
        Log.i(TAG, "SOUNDPOOL LOAD COMPLETE for sampleId:" + sampleId);

        loaded.put(sampleId, Boolean.TRUE);

        if (allSoundsLoaded()) {

            Log.i(TAG, "ALL SOUNDS LOADED! registering sensorManager");
            sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);

            Sensor accelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
            if (accelerometer == null) {
                Log.i(TAG, "accelerometer is null");
            } else {
                sensorManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL);
            }

            sprayButton.setEnabled(true);
            capOff();
        }
    }

    private boolean allSoundsLoaded() {
        Log.i(TAG, "allSoundsLoaded: loaded size:" + loaded.size());
        if (loaded.size() == SOUND_FILE_COUNT * 2 + 2) {
            Log.i(TAG,
                    "allSoundsLoaded: loaded.containsValue(Boolean.FALSE):" + loaded.containsValue(Boolean.FALSE));
            return !loaded.containsValue(Boolean.FALSE);
        }
        return false;
    }

    @Override
    public void onSensorChanged(SensorEvent event) {
        if (event.values == null) {
            return;
        }

        float x = event.values[0];
        float y = event.values[1];
        if (!sensorsInitialized) {
            lastX = x;
            lastY = y;
            sensorsInitialized = true;
            Log.i(TAG, "onSensorChanged: : SENSORS INITIALIZED");
        } else {
            float deltaX = Math.abs(lastX - x);
            float deltaY = Math.abs(lastY - y);
            if (deltaX < PREF_X_HORIZONTAL_SENSITIVITY_THRESHOLD)
                deltaX = (float) 0.0;
            if (deltaY < PREF_Y_VERTICAL_SENSITIVITY_THRESHOLD)
                deltaY = (float) 0.0;
            lastX = x;
            lastY = y;

            if (deltaY > deltaX) {
                shake("v");
            } else if (deltaX > deltaY) {
                shake("h");
            }
        }
    }

    @Override
    public void onAccuracyChanged(Sensor sensor, int accuracy) {
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private void initializeToolbar() {
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        toolbar.setTitle("");
        setSupportActionBar(toolbar);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            Window w = getWindow();
            w.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
                    WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);

            // Set paddingTop of toolbar to height of status bar.
            toolbar.setPadding(0, getStatusBarHeight(), 0, 0);
        }
    }

    private int getStatusBarHeight() {
        int result = 0;
        int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            result = getResources().getDimensionPixelSize(resourceId);
        }
        return result;
    }

    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private void initializeSoundPool() {
        if (soundPool != null) {
            soundPool.release();
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            AudioAttributes audioAttributes = new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_GAME)
                    .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION).build();

            soundPool = new SoundPool.Builder().setMaxStreams(PREF_SOUNDPOOL_MAX_STREAMS)
                    .setAudioAttributes(audioAttributes).build();
        } else {
            buildBeforeAPI21();
        }
        soundPool.setOnLoadCompleteListener(this);
    }

    @SuppressWarnings("deprecation")
    private void buildBeforeAPI21() {
        soundPool = new SoundPool(PREF_SOUNDPOOL_MAX_STREAMS, AudioManager.STREAM_MUSIC, 0);
    }

    private void initializeSprayButton() {
        sprayButton = (ImageView) findViewById(R.id.sprayButton);
        sprayButton.setEnabled(false);
        sprayButton.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                int action = event.getAction();
                if (action == MotionEvent.ACTION_DOWN) {
                    startSpray();
                } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
                    stopSpray();
                }
                return false;
            }
        });
    }

    private void loadPreferences() {
        PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
        SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);

        int newSoundpoolMaxSize = Integer.parseInt(sharedPref.getString(KEY_PREF_SOUNDPOOL_MAX_STREAMS, "4"));
        if (PREF_SOUNDPOOL_MAX_STREAMS != newSoundpoolMaxSize) {
            PREF_SOUNDPOOL_MAX_STREAMS = newSoundpoolMaxSize;
            initializeSoundPool();
        }

        PREF_USE_ALTERNATE_VERTICAL_SOUNDS = sharedPref.getBoolean(KEY_PREF_USE_ALTERNATE_VERTICAL_SOUNDS, false);
        PREF_X_HORIZONTAL_SENSITIVITY_THRESHOLD = sharedPref.getInt(KEY_PREF_X_HORIZONTAL_SENSITIVITY_THRESHOLD, 50)
                / 10.0f;
        PREF_Y_VERTICAL_SENSITIVITY_THRESHOLD = sharedPref.getInt(KEY_PREF_Y_VERTICAL_SENSITIVITY_THRESHOLD, 31)
                / 10.0f;

        Log.i(TAG, "loadPreferences. PREF_SOUNDPOOL_MAX_STREAMS:" + PREF_SOUNDPOOL_MAX_STREAMS);
        Log.i(TAG, "loadPreferences. PREF_USE_ALTERNATE_VERTICAL_SOUNDS:" + PREF_USE_ALTERNATE_VERTICAL_SOUNDS);
        Log.i(TAG, "loadPreferences. PREF_X_HORIZONTAL_SENSITIVITY_THRESHOLD:"
                + PREF_X_HORIZONTAL_SENSITIVITY_THRESHOLD);
        Log.i(TAG,
                "loadPreferences. PREF_Y_VERTICAL_SENSITIVITY_THRESHOLD:" + PREF_Y_VERTICAL_SENSITIVITY_THRESHOLD);
    }

    private void loadSoundResources() {
        for (int i = 0; i < SOUND_FILE_COUNT; i++) {
            String verticalShakeresourceName = PREF_USE_ALTERNATE_VERTICAL_SOUNDS ? "shake_v_a" + i
                    : "shake_v_b" + i;
            String horizontalShakeresourceName = "shake_h_" + i;
            shakeVerticalSoundIds[i] = soundPool.load(this,
                    getResources().getIdentifier(verticalShakeresourceName, "raw", "com.stillnojetpacks.huffr"), 1);
            shakeHorizontalSoundIds[i] = soundPool.load(this,
                    getResources().getIdentifier(horizontalShakeresourceName, "raw", "com.stillnojetpacks.huffr"),
                    1);
            loaded.put(shakeVerticalSoundIds[i], Boolean.FALSE);
            loaded.put(shakeHorizontalSoundIds[i], Boolean.FALSE);
        }
        spraySoundid = soundPool.load(this, R.raw.spray, 1);
        capOffSoundId = soundPool.load(this, R.raw.cap_off, 1);
        loaded.put(spraySoundid, Boolean.FALSE);
        loaded.put(capOffSoundId, Boolean.FALSE);
    }

    private void shake(@NonNull String axis) {
        int nextSoundId = "v".equals(axis) ? shakeVerticalSoundIds[random.nextInt(SOUND_FILE_COUNT)]
                : shakeHorizontalSoundIds[random.nextInt(SOUND_FILE_COUNT)];
        soundPool.play(nextSoundId, 1.0f, 1.0f, 1, 1, 1.0f);
    }

    private void capOff() {
        soundPool.play(capOffSoundId, 1.0f, 1.0f, 1, 0, 1.0f);
    }

    private void startSpray() {
        sprayStreamId = soundPool.play(spraySoundid, 0.65f, 0.65f, 2, -1, 1.0f);
    }

    private void stopSpray() {
        soundPool.stop(sprayStreamId);
    }

    private void share() {
        if (shareActionProvider != null) {
            String message = "huffr turns your android into a can of spray paint: " + uriForUrl("market://details");
            Intent shareIntent = new Intent();
            shareIntent.setAction(Intent.ACTION_SEND);
            shareIntent.putExtra(Intent.EXTRA_TEXT, message);
            shareIntent.setType("text/plain");
            shareActionProvider.setShareIntent(shareIntent);
        }
    }

    private void rateApp() {
        try {
            Intent rateIntent = rateIntentForUrl("market://details");
            startActivity(rateIntent);
        } catch (ActivityNotFoundException e) {
            Intent rateIntent = rateIntentForUrl("http://play.google.com/store/apps/details");
            startActivity(rateIntent);
        }
    }

    @SuppressWarnings("deprecation")
    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
    private Intent rateIntentForUrl(String url) {
        Intent intent = new Intent(Intent.ACTION_VIEW, uriForUrl(url));
        int flags = Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            flags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
        } else {
            flags |= Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET;
        }
        intent.addFlags(flags);
        return intent;
    }

    private Uri uriForUrl(String url) {
        return Uri.parse(String.format("%s?id=%s", url, getPackageName()));
    }

}