Java tutorial
/* * Copyright 2016 Carlo Eduardo Rodrguez Espino. * * 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 io.github.carlorodriguez.morningritual; import android.animation.Animator; import android.animation.ObjectAnimator; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.res.AssetFileDescriptor; import android.media.AudioAttributes; import android.media.AudioManager; import android.media.MediaPlayer; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Vibrator; import android.preference.PreferenceManager; import android.support.design.widget.AppBarLayout; import android.support.design.widget.FloatingActionButton; import android.support.v4.content.ContextCompat; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; import android.view.View; import android.view.Menu; import android.view.MenuItem; import android.view.WindowManager; import android.view.animation.LinearInterpolator; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; import java.io.IOException; import uk.co.deanwild.materialshowcaseview.MaterialShowcaseView; public class MainActivity extends AppCompatActivity { public static final int DEFAULT_STEP_MINUTE_DURATION = 3; public static final int DEFAULT_STEP_SECOND_DURATION = 20; private ObjectAnimator mAnimator; private MediaPlayer mMediaPlayer; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); setSupportActionBar(toolbar); final TextView title = (TextView) findViewById(R.id.title); final TextView quote = (TextView) findViewById(R.id.quote); final ProgressBar progressBar = (ProgressBar) findViewById(R.id.progressBar); final MorningRitual morningRitual = new MorningRitual(this); final FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab); fab.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (morningRitual.isStarted()) { if (morningRitual.isWaiting()) { setNextMorningRitualStep(progressBar, title, quote, morningRitual, fab); } else { stopMorningRitual(progressBar, title, quote, morningRitual, fab); } } else { startMorningRitual(progressBar, title, quote, morningRitual, fab); } } }); } @Override protected void onDestroy() { super.onDestroy(); if (mAnimator != null) { if (mAnimator.isStarted()) { mAnimator.removeAllListeners(); mAnimator.cancel(); } mAnimator = null; } if (mMediaPlayer != null) { mMediaPlayer = null; } } @Override protected void onPause() { super.onPause(); if (mMediaPlayer != null) { mMediaPlayer.release(); } } @Override protected void onResume() { super.onResume(); setLandscape(); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_main, menu); new Handler().post(new Runnable() { @Override public void run() { View view = findViewById(R.id.action_info); new MaterialShowcaseView.Builder(MainActivity.this).setTarget(view) .setDismissText(getString(R.string.got_it)).setContentText(getString(R.string.tutorial)) .singleUse(getString(R.string.showcase_info_id)).show(); } }); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { int id = item.getItemId(); switch (id) { case R.id.action_settings: startActivity(new Intent(this, PreferenceActivity.class)); return true; case R.id.action_info: startActivity(new Intent(this, InfoActivity.class)); return true; default: return super.onOptionsItemSelected(item); } } private void setLandscape() { AppBarLayout appBarLayout = (AppBarLayout) findViewById(R.id.app_bar); String landscape = getLandscape(); if (landscape.equalsIgnoreCase(getString(R.string.beach))) { appBarLayout.setBackgroundResource(R.drawable.landscape_beach_primary); } else if (landscape.equalsIgnoreCase(getString(R.string.beach_primary))) { appBarLayout.setBackgroundResource(R.drawable.landscape); } else if (landscape.equalsIgnoreCase(getString(R.string.snow))) { appBarLayout.setBackgroundResource(R.drawable.landscape_snow); } else if (landscape.equalsIgnoreCase(getString(R.string.valley))) { appBarLayout.setBackgroundResource(R.drawable.landscape_valley); } else if (landscape.equalsIgnoreCase(getString(R.string.nature))) { appBarLayout.setBackgroundResource(R.drawable.landscape_nature); } else if (landscape.equalsIgnoreCase(getString(R.string.mountains))) { appBarLayout.setBackgroundResource(R.drawable.landscape_mountains); } else if (landscape.equalsIgnoreCase(getString(R.string.dry))) { appBarLayout.setBackgroundResource(R.drawable.landscape_dry); } else { appBarLayout.setBackgroundColor(ContextCompat.getColor(this, R.color.colorPrimary)); } } private boolean vibrateWhenStepFinish() { final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); return prefs.getBoolean(getString(R.string.settings_vibration_key), true); } private boolean soundWhenStepFinish() { final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); return prefs.getBoolean(getString(R.string.settings_notification_sound_key), true); } private boolean automaticallySetStep() { final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); return prefs.getBoolean(getString(R.string.settings_auto_set_next_step_key), true); } private String getLandscape() { final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); return prefs.getString(getString(R.string.settings_landscape_key), getString(R.string.beach)); } private void playLegacyNotificationSound() throws IOException { AssetFileDescriptor afd = getResources().openRawResourceFd(R.raw.sound); if (afd == null) throw new IOException(); if (mMediaPlayer != null) { mMediaPlayer.release(); } mMediaPlayer = new MediaPlayer(); mMediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength()); afd.close(); mMediaPlayer.setAudioStreamType(AudioManager.STREAM_NOTIFICATION); mMediaPlayer.prepare(); mMediaPlayer.start(); } private void notifyStepFinish() { if (vibrateWhenStepFinish()) { ((Vibrator) getSystemService(Context.VIBRATOR_SERVICE)).vibrate(500); } if (soundWhenStepFinish()) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { AudioAttributes audioAttributes = new AudioAttributes.Builder() .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) .setUsage(AudioAttributes.USAGE_NOTIFICATION).build(); AudioManager audioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); MediaPlayer.create(this, R.raw.sound, audioAttributes, audioManager.generateAudioSessionId()) .start(); } else { try { playLegacyNotificationSound(); } catch (IOException e) { Toast.makeText(MainActivity.this, R.string.cannot_load_notification_sound, Toast.LENGTH_SHORT) .show(); } } } } private long getStepDurationInMillis(MorningRitual morningRitual) { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); int minuteStepTime = DEFAULT_STEP_MINUTE_DURATION; int secondStepTime = DEFAULT_STEP_SECOND_DURATION; if (morningRitual.isGratitude()) { minuteStepTime = prefs.getInt(getString(R.string.settings_gratitude_minute_time_key), MainActivity.DEFAULT_STEP_MINUTE_DURATION); secondStepTime = prefs.getInt(getString(R.string.settings_gratitude_second_time_key), MainActivity.DEFAULT_STEP_SECOND_DURATION); } else if (morningRitual.isHealth()) { minuteStepTime = prefs.getInt(getString(R.string.settings_health_minute_time_key), MainActivity.DEFAULT_STEP_MINUTE_DURATION); secondStepTime = prefs.getInt(getString(R.string.settings_health_second_time_key), MainActivity.DEFAULT_STEP_SECOND_DURATION); } else if (morningRitual.isVisualization()) { minuteStepTime = prefs.getInt(getString(R.string.settings_visualization_minute_time_key), MainActivity.DEFAULT_STEP_MINUTE_DURATION); secondStepTime = prefs.getInt(getString(R.string.settings_visualization_second_time_key), MainActivity.DEFAULT_STEP_SECOND_DURATION); } return (minuteStepTime * 60 * 1000) + (secondStepTime * 1000); } private void startMorningRitual(final ProgressBar progressBar, final TextView title, final TextView quote, final MorningRitual morningRitual, final FloatingActionButton fab) { title.setText(getString(R.string.gratitude_title)); quote.setText(getString(R.string.gratitude_quote)); morningRitual.reset(); morningRitual.start(); mAnimator = setAnimation(progressBar, title, quote, morningRitual, fab); mAnimator.start(); fab.setImageDrawable(ContextCompat.getDrawable(MainActivity.this, R.drawable.ic_fab_stop)); } private void stopMorningRitual(final ProgressBar progressBar, final TextView title, final TextView quote, final MorningRitual morningRitual, final FloatingActionButton fab) { mAnimator.removeAllListeners(); mAnimator.cancel(); morningRitual.stop(); title.setText(getString(R.string.gratitude_title)); quote.setText(getString(R.string.gratitude_quote)); progressBar.setProgress(0); fab.setImageDrawable(ContextCompat.getDrawable(MainActivity.this, R.drawable.ic_fab_play)); } private void updateUIForNextStep(final TextView title, final int titleResId, final TextView quote, final int quoteResId, final ProgressBar progressBar, final MorningRitual morningRitual, final FloatingActionButton fab) { title.setText(getString(titleResId)); quote.setText(getString(quoteResId)); progressBar.clearAnimation(); mAnimator = setAnimation(progressBar, title, quote, morningRitual, fab); mAnimator.start(); } private void updateUI(final ProgressBar progressBar, final TextView title, final TextView quote, final MorningRitual morningRitual, final FloatingActionButton fab) { if (morningRitual.isGratitude()) { updateUIForNextStep(title, R.string.gratitude_title, quote, R.string.gratitude_quote, progressBar, morningRitual, fab); } else if (morningRitual.isHealth()) { updateUIForNextStep(title, R.string.health_title, quote, R.string.health_quote, progressBar, morningRitual, fab); } else if (morningRitual.isVisualization()) { updateUIForNextStep(title, R.string.visualization_title, quote, R.string.visualization_quote, progressBar, morningRitual, fab); } else if (morningRitual.isFinished()) { title.setText(getString(R.string.finished)); quote.setText(getString(R.string.finished_quote)); fab.setImageDrawable(ContextCompat.getDrawable(MainActivity.this, R.drawable.ic_fab_refresh)); morningRitual.stop(); } } private void setNextMorningRitualStep(final ProgressBar progressBar, final TextView title, final TextView quote, final MorningRitual morningRitual, final FloatingActionButton fab) { if (morningRitual.isAutomatic() || morningRitual.isFinished()) { updateUI(progressBar, title, quote, morningRitual, fab); } else if (morningRitual.isWaiting()) { morningRitual.waitForUser(false); updateUI(progressBar, title, quote, morningRitual, fab); fab.setImageDrawable(ContextCompat.getDrawable(MainActivity.this, R.drawable.ic_fab_stop)); } else { morningRitual.waitForUser(true); fab.setImageDrawable(ContextCompat.getDrawable(MainActivity.this, R.drawable.ic_fab_navigate_next)); } } private ObjectAnimator setAnimation(final ProgressBar progressBar, final TextView title, final TextView quote, final MorningRitual morningRitual, final FloatingActionButton fab) { final ObjectAnimator animator = ObjectAnimator.ofInt(progressBar, "progress", 0, 200000); animator.setDuration(getStepDurationInMillis(morningRitual)); animator.setInterpolator(new LinearInterpolator()); animator.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) { } @Override public void onAnimationEnd(Animator animation) { notifyStepFinish(); morningRitual.nextStep(); setNextMorningRitualStep(progressBar, title, quote, morningRitual, fab); } @Override public void onAnimationCancel(Animator animation) { } @Override public void onAnimationRepeat(Animator animation) { } }); return animator; } class MorningRitual { private final int GRATITUDE = 0; private final int HEALTH = 1; private final int VISUALIZATION = 2; private final int FINISHED = 3; private int current; private boolean started; private boolean waiting; private Activity activity; public MorningRitual(Activity activity) { this.activity = activity; setup(); } private void setup() { current = GRATITUDE; started = false; waiting = false; } public void reset() { setup(); } public void start() { started = true; activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); } public void stop() { reset(); activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); } public boolean isStarted() { return started; } /** * If the app will automatically set next step this returns true. * * @return Return true if morning ritual will automatically set next * step. */ public boolean isAutomatic() { return automaticallySetStep(); } /** * Set if the morning ritual needs to wait until the user manually sets * the next step. * * @param wait If morning ritual should wait for user to set next step. */ public void waitForUser(boolean wait) { waiting = wait; } /** * If user will manually set next step this returns true if morning * ritual is waiting for the user to manually set the next step. * * @return If the user will manually set next step. */ public boolean isWaiting() { return waiting; } /** * Set next step of morning ritual. */ public void nextStep() { switch (current) { case GRATITUDE: current = HEALTH; break; case HEALTH: current = VISUALIZATION; break; case VISUALIZATION: current = FINISHED; break; default: current = FINISHED; break; } } public boolean isGratitude() { return current == GRATITUDE; } public boolean isHealth() { return current == HEALTH; } public boolean isVisualization() { return current == VISUALIZATION; } public boolean isFinished() { return current == FINISHED; } } }