Java tutorial
package com.smp.musicspeed; import static com.smp.musicspeed.TextHelper.*; import static com.smp.musicspeed.UtilityMethods.*; import java.io.File; import java.io.IOException; 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.ipaulpro.afilechooser.utils.FileUtils; import com.pheelicks.visualizer.VisualizerView; import com.pheelicks.visualizer.renderer.BarGraphRenderer; import com.smp.musicspeed.AdjustmentFragment.OnNumberEnteredListener; import com.smp.musicspeed.ImportDialogFragment.ImportDialogFragmentListener; import com.smp.musicspeed.PlayFileService.SoundStreamControlBinder; import com.smp.soundtouchandroid.SoundStreamRuntimeException; import static com.smp.musicspeed.Constants.*; import android.media.audiofx.Visualizer; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.IBinder; import android.animation.Animator; import android.animation.Animator.AnimatorListener; import android.animation.AnimatorListenerAdapter; import android.app.ActivityManager; import android.app.ActivityManager.RunningServiceInfo; import android.app.Notification; import android.app.Service; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.content.SharedPreferences; import android.graphics.Color; import android.graphics.Paint; import android.support.v4.app.FragmentActivity; import android.support.v7.app.ActionBarActivity; import android.support.v7.widget.SwitchCompat; import android.support.v7.widget.Toolbar; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.animation.Animation; import android.view.animation.Animation.AnimationListener; import android.view.animation.AnimationUtils; import android.view.animation.AnticipateOvershootInterpolator; import android.view.animation.BounceInterpolator; import android.view.animation.TranslateAnimation; import android.widget.CompoundButton; import android.widget.CompoundButton.OnCheckedChangeListener; import android.widget.FrameLayout; import android.widget.ImageButton; import android.widget.SeekBar; import android.widget.SeekBar.OnSeekBarChangeListener; import android.widget.Switch; import android.widget.TextSwitcher; import android.widget.TextView; import android.widget.Toast; import android.widget.ViewFlipper; public class MainActivity extends ActionBarActivity implements OnNumberEnteredListener, ImportDialogFragmentListener { private static final String MY_AD_UNIT_ID = "ca-app-pub-7592316401695950/1294338224"; private static final String TEST_DEVICE = "54BEF252B42F93A4F19036ABE8E1CDDB"; private static final int REQUEST_CODE = 6384; private static final int LINKED_VIEW = 1; private static final int UNLINKED_VIEW = 0; private static final float SLOW_SPEED_RANGE = 0.67f; private static final float SLOW_SPEED_MIN = 0.33f; private static final float FAST_SPEED_RANGE = 2.0f; private static final float FAST_SPEED_MIN = 1.0f; private static final float FAST_SPEED_MAX = FAST_SPEED_MIN + FAST_SPEED_RANGE; private static final float PITCH_MAX = 12.0f; private static final float PITCH_MIN = -12.0f; private static final float DECIMAL_PLACES_TEMPO = 100.0f; private static final float DECIMAL_PLACES_PITCH = 10.0f; private static final int BEGINNING_OF_FILE = 0; private static final String FILE = ""; private static final long US_IN_MIN = 60000000; private static final long US_IN_SEC = 1000000; private static final String BLANK_TIME = "--:--"; private int DEFAULT_PROGRESS_PITCH; private int DEFAULT_PROGRESS_TEMPO; private int DEFAULT_PROGRESS_RATE; private SeekBar playBar, pitchBar, tempoBar, rateBar; private VisualizerView visualizerView; private AdView adView; private TextView pitchText, tempoText, rateText, fileText; private TextView timeText, durationText; private View loopImage; private PlayFileService service; private SeekBarListener seekListen; private ImageButton playButton, loopStartButton, loopEndButton, loopClearButton; private ImageButton tempoKeysButton, pitchKeysButton, rateKeysButton; private SwitchCompat linkSwitch; private InterstitialAd interstitial; private Intent oldIntent; private View tempoCard, pitchCard, rateCard; // private TextSwitcher rateSwitcher; // private FrameLayout cardFrame; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); DEFAULT_PROGRESS_PITCH = getResources().getInteger(R.integer.default_progress_pitch); DEFAULT_PROGRESS_TEMPO = getResources().getInteger(R.integer.default_progress_tempo); DEFAULT_PROGRESS_RATE = getResources().getInteger(R.integer.default_progress_rate); playBar = (SeekBar) findViewById(R.id.seek_play); tempoBar = (SeekBar) findViewById(R.id.seek_tempo); pitchBar = (SeekBar) findViewById(R.id.seek_pitch); rateBar = (SeekBar) findViewById(R.id.seek_rate); pitchText = (TextView) findViewById(R.id.pitch_text); tempoText = (TextView) findViewById(R.id.tempo_text); rateText = (TextView) findViewById(R.id.rate_text); fileText = (TextView) findViewById(android.R.id.title); timeText = (TextView) findViewById(R.id.text_time); durationText = (TextView) findViewById(R.id.text_duration); loopImage = findViewById(R.id.img_loop); playButton = (ImageButton) findViewById(R.id.button_play); loopStartButton = (ImageButton) findViewById(R.id.button_loop_start); loopEndButton = (ImageButton) findViewById(R.id.button_loop_end); loopClearButton = (ImageButton) findViewById(R.id.button_loop_clear); tempoKeysButton = (ImageButton) findViewById(R.id.button_keys_tempo); pitchKeysButton = (ImageButton) findViewById(R.id.button_keys_pitch); rateKeysButton = (ImageButton) findViewById(R.id.button_keys_rate); linkSwitch = (SwitchCompat) findViewById(R.id.link_toggle); // rateSwitcher = (TextSwitcher) findViewById(R.id.rate_switcher); tempoCard = findViewById(R.id.card_tempo); pitchCard = findViewById(R.id.card_pitch); rateCard = findViewById(R.id.card_rate); // pitchTempoCards = findViewById(R.id.pitch_tempo_cards); // cardFrame = (ViewFlipper) findViewById(R.id.card_frame); /* * Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar); * toolbar.setTitle(""); setSupportActionBar(toolbar); */ getSupportActionBar().setTitle(""); seekListen = new SeekBarListener(); playBar.setOnSeekBarChangeListener(seekListen); tempoBar.setOnSeekBarChangeListener(seekListen); pitchBar.setOnSeekBarChangeListener(seekListen); rateBar.setOnSeekBarChangeListener(seekListen); if (Build.VERSION.SDK_INT >= 21) { getSupportActionBar().setElevation(0); } readPrefs(); linkSwitch.setOnCheckedChangeListener(new OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton arg0, boolean arg1) { handleSwitch(); } }); visualizerView = (VisualizerView) findViewById(R.id.visualizer_view); addBarGraphRenderers(); adView = (AdView) this.findViewById(R.id.adview); AdRequest adRequest = new AdRequest.Builder().addTestDevice(AdRequest.DEVICE_ID_EMULATOR) .addTestDevice(TEST_DEVICE).build(); adView.setAdListener(new AdListener() { @Override public void onAdLoaded() { adView.setVisibility(View.VISIBLE); } @Override public void onAdFailedToLoad(int code) { adView.setVisibility(View.GONE); } }); adView.loadAd(adRequest); initInterstitialAd(); cleanUp(); } private static final String PREF_NAME = "com.smp.musicspeed.prefs"; private static final String PREF_LINKED = "com.smp.musicspeed.prefs.LINKED"; private void readPrefs() { Context mContext = getApplicationContext(); SharedPreferences prefs = mContext.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE); boolean linked = prefs.getBoolean(PREF_LINKED, false); if (linked) { linkSwitch.setChecked(linked); pitchCard.setVisibility(View.GONE); tempoCard.setVisibility(View.GONE); rateCard.setVisibility(View.VISIBLE); } } private void writePrefs() { Context mContext = getApplicationContext(); SharedPreferences prefs = mContext.getSharedPreferences(PREF_NAME, Context.MODE_PRIVATE); SharedPreferences.Editor editor = prefs.edit(); editor.putBoolean(PREF_LINKED, linkSwitch.isChecked()); editor.commit(); } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); outState.putBoolean("com.smp.linked", linkSwitch.isChecked()); } @Override protected void onRestoreInstanceState(Bundle savedState) { super.onRestoreInstanceState(savedState); } public void onClickOpen(View view) { showChooser(); } public void onResetClicked(View view) { resetSeekbars(); String st = getResources().getString(R.string.original_values); makeToastShort(st); } private void linkOn() { resetSeekbars(); pitchCard.setVisibility(View.GONE); tempoCard.setVisibility(View.GONE); rateCard.setVisibility(View.VISIBLE); } private void linkOff() { resetSeekbars(); pitchCard.setVisibility(View.VISIBLE); tempoCard.setVisibility(View.VISIBLE); rateCard.setVisibility(View.GONE); } private void resetSeekbars() { rateBar.setProgress(rateBar.getMax() / 2); pitchBar.setProgress(pitchBar.getMax() / 2); tempoBar.setProgress(tempoBar.getMax() / 2); } private static final int TRANS_ANIMATION_TIME = 700; private static final int TEXT_ANIMATION_TIME = 400; private void animateLinkOn() { TranslateAnimation anim = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, -1.0f); anim.setDuration(TRANS_ANIMATION_TIME); anim.setInterpolator(new AnticipateOvershootInterpolator()); anim.setAnimationListener(new AnimationListenerAdaptor() { @Override public void onAnimationEnd(Animation animation) { rateText.setAlpha(0f); linkOn(); rateText.animate().alpha(1f).setDuration(TRANS_ANIMATION_TIME) .setListener(new AnimatorListenerAdapter() { }); } }); tempoCard.startAnimation(anim); tempoText.animate().alpha(0f).setDuration(TEXT_ANIMATION_TIME).setListener(new AnimatorListenerAdapter() { }); } private void animateLinkOff() { linkOff(); tempoCard.setVisibility(View.INVISIBLE); TranslateAnimation anim = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 1.0f); anim.setDuration(TRANS_ANIMATION_TIME); anim.setInterpolator(new AnticipateOvershootInterpolator()); anim.setAnimationListener(new AnimationListenerAdaptor() { @Override public void onAnimationEnd(Animation animation) { tempoText.setAlpha(0f); linkOff(); tempoText.animate().alpha(1f).setDuration(TEXT_ANIMATION_TIME) .setListener(new AnimatorListenerAdapter() { }); } }); rateCard.startAnimation(anim); rateText.animate().alpha(0f).setDuration(TRANS_ANIMATION_TIME).setListener(new AnimatorListenerAdapter() { }); } public void handleSwitch() { boolean on = linkSwitch.isChecked(); if (on) { animateLinkOn(); } else { animateLinkOff(); } } public void onToggleClicked(final View view) { } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); setIntent(intent); } @Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.action_share: startShare(); break; case R.id.action_save: startSave(); break; case R.id.action_open: showChooser(); break; case R.id.action_licenses: startActivity(new Intent(this, LicenseActivity.class)); break; } return true; } private void startShare() { Intent intent = new Intent(android.content.Intent.ACTION_SEND); intent.setType("text/plain"); intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); // Add data to the intent, the receiving app will decide what to do with // it. String fileName = null; if (service != null && service.getFileName() != null) { fileName = new File(service.getFileName()).getName(); } String music = fileName == null ? "music" : fileName; intent.putExtra(Intent.EXTRA_SUBJECT, "Music Speed Changer"); intent.putExtra(Intent.EXTRA_TEXT, "I'm listening to " + music + " at a different tempo and pitch with Music Speed Changer, available at Google Play: " + "https://play.google.com/store/apps/details?id=com.smp.musicspeed"); startActivity(Intent.createChooser(intent, "How do you want to share?")); } private void startSave() { String fileName = service.getFileName(); if (!(fileName == null)) { if (!isMyServiceRunning(this, FileWriterService.class)) { Intent intent = new Intent(this, FileWriterService.class); intent.putExtra(INTENT_FILE_NAME_IN, fileName); intent.putExtra(INTENT_TEMPO, service.getTempo()); intent.putExtra(INTENT_PITCH, service.getPitchSemi()); intent.putExtra(INTENT_RATE, service.getRate()); intent.putExtra(INTENT_LINKED, linkSwitch.isChecked()); startService(intent); if (interstitial.isLoaded()) interstitial.show(); } else { makeToastShort(TOAST_SERVICE_RUNNING); } } else { makeToastShort(TOAST_SELECT_FILE); } } private void initInterstitialAd() { interstitial = new InterstitialAd(this); interstitial.setAdUnitId(MY_AD_UNIT_ID); } private ServiceConnection serviceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName className, IBinder iBinder) { SoundStreamControlBinder binder = (SoundStreamControlBinder) iBinder; MainActivity.this.service = binder.getService(); binder.setListener(new PlayFileBoundServiceListener() { @Override public void onProgressChanged(int track, final double currentPercentage, long position) { if (!seekListen.getPlayTouched()) { int maxProgress = playBar.getMax(); int currentProgress = (int) Math.floor(maxProgress * currentPercentage); playBar.setProgress(currentProgress); setPlayedTime(position); } } @Override public void onTrackFinished(int track) { playBar.post(new Runnable() { @Override public void run() { setPlayImage(); // playBar.setProgress(0); // setPlayedTime(service.getPlayedDuration()); } }); } @Override public void releaseServiceReference() { service = null; } @Override public void shouldChangePlayImage() { setPlayImage(); } @Override public void onExceptionThrown() { MainActivity.this.makeToastShort(TOAST_PROBLEM_PLAYING); MainActivity.this.onInvalidFile(); } }); // pendingFile is not null if the service has been stopped via the // notification // and the user is in the file chooser. if (pendingFile != null) { try { Log.d("FILE", "onNewFile() called on " + pendingFile); onNewFile(pendingFile); } catch (IOException e) { logException(Log.getStackTraceString(e)); e.printStackTrace(); onInvalidFile(); } catch (SoundStreamRuntimeException e) { logException(Log.getStackTraceString(e)); e.printStackTrace(); onInvalidFile(); } pendingFile = null; } if (getIntent() != null && getIntent().getAction() == Intent.ACTION_VIEW && !isMyServiceRunning(MainActivity.this, HardPathService.class)) { processNewFileIntent(getIntent()); } // TODO Refactor this? setPitchText(service.getPitchSemi()); setTempoText(service.getTempo()); setRateText(service.getRate()); setPitchBar(service.getPitchSemi()); setTempoBar(service.getTempo()); setRateBar(service.getRate()); setPlayBar(service.getPlayedDuration()); initVisualizerView(); determineLooping(); setDurationText(service.getDuration()); setPlayedTime(service.getPlayedDuration()); String file = service.getFileName(); showFileName(file); uiEnabled(file != null); setPlayImage(); // stopServiceForeground(); } private void setPlayBar(long playedDuration) { int maxProgress = playBar.getMax(); long pd = service.getPlayedDuration(); long d = service.getDuration(); double cp = pd == 0 ? 0 : (double) pd / d; int currentProgress = (int) Math.round(maxProgress * cp); if (pd == PlayFileService.NOT_SET) currentProgress = 0; playBar.setProgress(currentProgress); } private void setTempoBar(float tempo) { int progress = calculateProgressFromTempo(tempo); tempoBar.setProgress(progress); } private void setRateBar(float rate) { int progress = calculateProgressFromRate(rate); rateBar.setProgress(progress); } private void setPitchBar(float pitchSemi) { int progress = calculateProgressFromPitch(pitchSemi); pitchBar.setProgress(progress); } @Override public void onServiceDisconnected(ComponentName arg0) { } }; private String pendingFile; private void startServiceForeground() { Notification not = NotificationHelper.generatePlayFileNotification(this, false, service.getFileName(), service.getPitchSemi(), service.getTempo(), service.getRate()); service.startForeground(ID_PLAYER_NOTIFICATION, not); } private void stopServiceForeground() { service.stopForeground(true); } private void determineLooping() { if (service.isLooping()) loopImage.setVisibility(View.VISIBLE); else loopImage.setVisibility(View.INVISIBLE); } private void setTempoText(float tempo) { tempoText.setText(TEMPO + getFormattedTempo(tempo)); } private void setRateText(float rateChange) { rateText.setText(RATE + getFormattedRate(rateChange)); } private void setPitchText(float pitch) { pitchText.setText(PITCH + getFormattedPitch(pitch)); } private void uiEnabled(boolean value) { playBar.setEnabled(value); pitchBar.setEnabled(value); tempoBar.setEnabled(value); rateBar.setEnabled(value); tempoKeysButton.setEnabled(value); pitchKeysButton.setEnabled(value); rateKeysButton.setEnabled(value); } @Override protected void onStop() { super.onStop(); } @Override protected void onStart() { super.onStart(); } @Override protected void onPause() { if (adView != null) { adView.pause(); } if (service != null) { if (!service.isPaused() && !(service.getFileName() == null)) startServiceForeground(); /* * if (service.hasVisualizer()) service.setVisualizerEnabled(false); */ } unbindService(serviceConnection); super.onPause(); } @Override protected void onResume() { super.onResume(); if (adView != null) { adView.resume(); } if (service != null) { stopServiceForeground(); setPlayImage(); /* * if (service.hasVisualizer()) service.setVisualizerEnabled(true); */ } if (!interstitial.isLoaded()) { AdRequest adRequest = new AdRequest.Builder().addTestDevice(TEST_DEVICE).build(); interstitial.loadAd(adRequest); } Intent intent = new Intent(this, PlayFileService.class); startService(intent); bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE); } @Override protected void onDestroy() { if (service != null) service.releaseListener(); service = null; if (adView != null) adView.destroy(); writePrefs(); System.gc(); super.onDestroy(); } private void cleanUp() { if (!isMyServiceRunning(this, PlayFileService.class) && !isMyServiceRunning(this, FileWriterService.class) && !isMyServiceRunning(this, HardPathService.class)) { try { FileMethods.deleteTempDir(); } catch (Exception e) { logException(Log.getStackTraceString(e)); e.printStackTrace(); } } } private float calculatePitch(int progress) { return (progress - DEFAULT_PROGRESS_PITCH) / DECIMAL_PLACES_PITCH; } private float calculateRate(int progress) { return calculateTempo(progress); } private float calculateTempo(int progress) { float tempo; float percentage = (float) progress / DEFAULT_PROGRESS_TEMPO; if (progress >= DEFAULT_PROGRESS_TEMPO) { tempo = Math.round((percentage * FAST_SPEED_RANGE - FAST_SPEED_MIN) * DECIMAL_PLACES_TEMPO) / DECIMAL_PLACES_TEMPO; } else { tempo = Math.round((percentage * SLOW_SPEED_RANGE + SLOW_SPEED_MIN) * DECIMAL_PLACES_TEMPO) / DECIMAL_PLACES_TEMPO; } return tempo; } private int calculateProgressFromPitch(double pitch) { return (int) Math.round(pitch * DECIMAL_PLACES_PITCH + DEFAULT_PROGRESS_PITCH); } private int calculateProgressFromRate(double rate) { return calculateProgressFromTempo(rate); } private int calculateProgressFromTempo(double tempo) { int progress; double percentage; if (tempo >= FAST_SPEED_MIN) { percentage = (tempo + FAST_SPEED_MIN) / FAST_SPEED_RANGE; } else { percentage = (tempo - SLOW_SPEED_MIN) / SLOW_SPEED_RANGE; } progress = (int) Math.round(percentage * DEFAULT_PROGRESS_TEMPO); return progress; } private class SeekBarListener implements OnSeekBarChangeListener { private boolean playTouched; private int playSeek; boolean getPlayTouched() { return playTouched; } @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { if (seekBar == pitchBar) { float pitch = calculatePitch(progress); if (service != null) { service.setPitch(pitch); setPitchText(pitch); } } else if (seekBar == tempoBar) { float tempo = calculateTempo(progress); if (service != null) { service.setTempo(tempo); setTempoText(tempo); } } else if (seekBar == rateBar) { float rate = calculateRate(progress); if (service != null) { service.setRate(rate); setRateText(rate); } } else if (seekBar == playBar && fromUser) { playSeek = progress; } } @Override public void onStartTrackingTouch(SeekBar seekBar) { if (seekBar == playBar) playTouched = true; } @Override public void onStopTrackingTouch(SeekBar seekBar) { if (seekBar == playBar) { playBar.post(new Runnable() { @Override public void run() { playTouched = false; float percentage = (float) playSeek / playBar.getMax(); if (service != null) { service.seekTo(percentage); setPlayedTime(service.getPlayedDuration()); } } }); } } } private void addBarGraphRenderers() { Paint paint = new Paint(); paint.setStrokeWidth(10.5f); paint.setAntiAlias(true); paint.setColor(Color.argb(255, 144, 202, 249)); BarGraphRenderer barGraphRendererBottom = new BarGraphRenderer(4, paint, false); visualizerView.addRenderer(barGraphRendererBottom); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.main, menu); return true; } public void onPlay(View view) { if (service.getFileName() == null) { makeToastShort(TOAST_SELECT_FILE); } else { service.onPlayCommand(); setPlayImage(); if (service.isPaused()) { visualizerView.postDelayed(new Runnable() { @Override public void run() { if (visualizerView != null && service != null && service.isPaused()) visualizerView.setVisibility(View.INVISIBLE); } }, 2000); } else { visualizerView.setVisibility(View.VISIBLE); } } } private void setPlayImage() { if (service.isPaused()) { playButton.setImageResource(R.drawable.ic_play_circle_fill_grey600_36dp); } else { playButton.setImageResource(R.drawable.ic_pause_circle_fill_grey600_36dp); } } private void showFileName(String fullPath) { if (fullPath != null) { String nameOnly = new File(fullPath).getName(); fileText.setText(FILE + nameOnly); } else { fileText.setText(getResources().getString(R.string.header_file)); } } private void showChooser() { Intent target = createAudioContentIntent(); Intent intent = Intent.createChooser(target, getString(R.string.chooser_title)); startActivityForResult(intent, REQUEST_CODE); } private Intent createAudioContentIntent() { final Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.setType("audio/*"); intent.addCategory(Intent.CATEGORY_OPENABLE); // intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true); return intent; } private class Time implements Comparable { private int min; private int sec; Time(long us) { min = (int) (us / US_IN_MIN); sec = (int) Math.floor((us % US_IN_MIN / (double) US_IN_SEC)); } @Override public String toString() { return "" + min + ":" + String.format("%02d", sec); } @Override public int compareTo(Object arg) { Time other = (Time) arg; if (min == other.min && sec == other.sec) return 0; if (min == other.min) { if (sec > other.sec) return 1; return -1; } if (min > other.min) return 1; return -1; } } private void setDurationText(long time) { if (time < 0) { durationText.setText(BLANK_TIME); } else { Time duration = new Time(time); durationText.setText(duration.toString()); } } private void setPlayedTime(long time) { if (time < 0) { timeText.setText(BLANK_TIME); } else { Time played = new Time(time); Time duration = new Time(service.getDuration()); if (played.compareTo(duration) > 0) played = duration; timeText.setText(played.toString()); } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { visualizerView.setVisibility(View.INVISIBLE); switch (requestCode) { case REQUEST_CODE: if (resultCode == RESULT_OK && data != null) { oldIntent = getIntent(); data.setAction(Intent.ACTION_VIEW); setIntent(data); // processNewFileIntent(data); } break; } super.onActivityResult(requestCode, resultCode, data); } @Override public void onFilePathReceived(String filePath) { if (filePath != null) { Uri fileUri = Uri.fromFile(new File(filePath)); Intent uriIntent = new Intent(); uriIntent.setAction(Intent.ACTION_VIEW); uriIntent.setData(fileUri); setIntent(uriIntent); } processNewFilePath(filePath); } @Override public void onImportCancelled() { setIntent(oldIntent); } private void processNewFileIntent(Intent data) { String filePath = FileUtils.getPath(this, data.getData()); if (filePath != null) { processNewFilePath(filePath); } else { ImportDialogFragment dialog = ImportDialogFragment.newInstance(data.getData()); dialog.show(getFragmentManager(), "ImportDialogFragment"); } } private void processNewFilePath(String filePath) { try { if (filePath == null) { makeToastShort(TOAST_INVALID_FILE); // onInvalidFile(); } else if (service == null) { // Log.d("FILE", "service == null"); pendingFile = filePath; } else if (!filePath.equals(service.getFileName())) { onNewFile(filePath); } } catch (IOException e) { logException(Log.getStackTraceString(e)); e.printStackTrace(); makeToastShort(TOAST_INVALID_FILE); onInvalidFile(); } catch (SoundStreamRuntimeException e) { logException(Log.getStackTraceString(e)); e.printStackTrace(); makeToastShort(TOAST_INVALID_FILE); onInvalidFile(); } catch (IllegalArgumentException e) { logException(Log.getStackTraceString(e)); e.printStackTrace(); makeToastShort(TOAST_INVALID_FILE); onInvalidFile(); } } private void onInvalidFile() { service.reset(); prepareUIForNewFile(); } private void onNewFile(String fileName) throws IOException { playBar.setOnSeekBarChangeListener(null); if (fileName != null) { service.initAudioFile(fileName); } prepareUIForNewFile(); } private void prepareUIForNewFile() { String fileName = service.getFileName(); resetUI(); uiEnabled(service.isPlayable()); showFileName(fileName); initVisualizerView(); } private void makeToastShort(String text) { Toast.makeText(this, text, Toast.LENGTH_SHORT).show(); } private void initVisualizerView() { Visualizer v = service.getVisualizer(); if (v != null) visualizerView.link(v); } private void resetUI() { playBar.post(new Runnable() { @Override public void run() { determineLooping(); playBar.setProgress(BEGINNING_OF_FILE); pitchBar.setProgress(DEFAULT_PROGRESS_PITCH); tempoBar.setProgress(DEFAULT_PROGRESS_TEMPO); rateBar.setProgress(DEFAULT_PROGRESS_RATE); playButton.setImageResource(R.drawable.ic_play_circle_fill_grey600_36dp); setDurationText(service.getDuration()); setPlayedTime(service.getPlayedDuration()); playBar.setOnSeekBarChangeListener(seekListen); } }); } private void showAdjustmentFragmentDialog(int adjustment) { AdjustmentFragment frag = new AdjustmentFragment(); Bundle args = new Bundle(); args.putInt(BUNDLE_ADJUSTMENT, adjustment); frag.setArguments(args); frag.show(getSupportFragmentManager(), "Adjustment Fragment"); } public void onPitchKeys(View view) { showAdjustmentFragmentDialog(AdjustmentFragment.ADJUSTMENT_PITCH); } public void onTempoKeys(View view) { showAdjustmentFragmentDialog(AdjustmentFragment.ADJUSTMENT_TEMPO); } public void onRateKeys(View view) { showAdjustmentFragmentDialog(AdjustmentFragment.ADJUSTMENT_RATE); } public void onLoopStart(View view) { if (service.getFileName() == null) { makeToastShort(TOAST_SELECT_FILE); } else { if (service.setLoopStart()) { makeToastShort("Loop start point set."); } else { makeToastShort(TOAST_INVALID_LOOP_TIME); } determineLooping(); } } public void onLoopEnd(View view) { if (service.getFileName() == null) { makeToastShort(TOAST_SELECT_FILE); } else { if (service.setLoopEnd()) { makeToastShort("Loop end point set."); } else { makeToastShort(TOAST_INVALID_LOOP_TIME); } determineLooping(); } } public void onLoopClear(View view) { if (service.getFileName() == null) { makeToastShort(TOAST_SELECT_FILE); } else { service.clearLoopPoints(); Toast.makeText(this, "Loop points cleared.", Toast.LENGTH_SHORT).show(); } determineLooping(); } @Override public void onNumberEntered(double num, int adjustment) { int progress; switch (adjustment) { case AdjustmentFragment.ADJUSTMENT_PITCH: if (num < PITCH_MIN) num = PITCH_MIN; else if (num > PITCH_MAX) num = PITCH_MAX; progress = calculateProgressFromPitch(num); pitchBar.setProgress(progress); float pitch = (float) num; service.setPitch(pitch); setPitchText(pitch); break; case AdjustmentFragment.ADJUSTMENT_TEMPO: num /= DECIMAL_PLACES_TEMPO; if (num < SLOW_SPEED_MIN) num = SLOW_SPEED_MIN; else if (num > FAST_SPEED_MAX) num = FAST_SPEED_MAX; progress = calculateProgressFromTempo(num); tempoBar.setProgress(progress); float tempo = (float) num; service.setTempo(tempo); setTempoText(tempo); break; case AdjustmentFragment.ADJUSTMENT_RATE: num /= DECIMAL_PLACES_TEMPO; if (num < SLOW_SPEED_MIN) num = SLOW_SPEED_MIN; else if (num > FAST_SPEED_MAX) num = FAST_SPEED_MAX; progress = calculateProgressFromRate(num); rateBar.setProgress(progress); float rate = (float) num; service.setRate(rate); setRateText(rate); break; default: throw new IllegalArgumentException("Not a valid adjustment"); } } static class AnimationListenerAdaptor implements Animation.AnimationListener { @Override public void onAnimationEnd(Animation animation) { // TODO Auto-generated method stub } @Override public void onAnimationRepeat(Animation animation) { // TODO Auto-generated method stub } @Override public void onAnimationStart(Animation animation) { // TODO Auto-generated method stub } } }