package com.architjn.acjmusicplayer.ui.layouts.fragments;
import android.animation.Animator;
import android.animation.ArgbEvaluator;
import android.animation.ValueAnimator;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.media.AudioManager;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.content.ContextCompat;
import android.support.v4.graphics.drawable.DrawableCompat;
import android.support.v4.view.animation.FastOutSlowInInterpolator;
import android.support.v7.graphics.Palette;
import android.support.v7.widget.AppCompatSeekBar;
import android.support.v7.widget.PopupMenu;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewAnimationUtils;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.SeekBar;
import android.widget.TextView;
import com.afollestad.async.Action;
import com.architjn.acjmusicplayer.R;
import com.architjn.acjmusicplayer.service.PlayerService;
import com.architjn.acjmusicplayer.task.ColorChangeAnimation;
import com.architjn.acjmusicplayer.ui.layouts.activity.AlbumActivity;
import com.architjn.acjmusicplayer.ui.layouts.activity.ArtistActivity;
import com.architjn.acjmusicplayer.ui.layouts.activity.MainActivity;
import com.architjn.acjmusicplayer.ui.widget.slidinguppanel.SlidingUpPanelLayout;
import com.architjn.acjmusicplayer.utils.ListSongs;
import com.architjn.acjmusicplayer.utils.Utils;
import com.architjn.acjmusicplayer.utils.handlers.PlayerDBHandler;
import com.architjn.acjmusicplayer.utils.handlers.UserPreferenceHandler;
import com.architjn.acjmusicplayer.utils.items.Song;
import com.squareup.picasso.Picasso;
import com.squareup.picasso.Target;
import java.io.File;
import java.util.Timer;
import java.util.TimerTask;
/**
* Created by architjn on 01/01/16.
*/
public class PlayerFragment extends Fragment {
private static final String TAG = "PlayerFragment-TAG";
private static final int MAX_ALPHA = 255, TRANS_ALPHA = 140;
private static int MAX_VOL;
public static final String ACTION_OPEN_PANEL = "ACTION_OPEN_PANEL";
public static final String ACTION_RECIEVE_SONG = "ACTION_RECIEVE_SONG";
public static View miniController;
private TextView miniSongTitle, largeSongTitle, navTitle, navSubTitle;
private Context context;
private View mainView, revealView;
private ImageView artHolder, navArt;
private SlidingUpPanelLayout slidingUpPanelLayout;
private Utils utils;
private PlayerState playerState;
private int size, colorLight, colorTo = 0xffffffff, colorDark;
private Timer timer;
private AppCompatSeekBar volumeSeekBar, seekBar;
private ImageView next, pause, prev, shuffle, repeat, noVolume,
fullVolume, playlist, waveIcon, backButton, overflowMenu;
private LinearLayout controllHolder, currentSongHolder;
private Song currentSong;
private TextView totalSeekText, currentSeekText;
private UserPreferenceHandler preferenceHandler;
private AudioManager audioManager;
private UpNextFragment upNextFragment;
private final BroadcastReceiver br = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
switch (intent.getAction()) {
case PlayerFragment.ACTION_RECIEVE_SONG:
if (intent.getLongExtra("songId", 0) != -1) {
if (slidingUpPanelLayout.isPanelHidden())
slidingUpPanelLayout.showPanel();
updatePlayer(intent);
if (intent.getBooleanExtra("running", false))
play();
else
pause();
} else {
slidingUpPanelLayout.hidePanel();
pause();
}
break;
case ACTION_OPEN_PANEL:
if (!slidingUpPanelLayout.isPanelExpanded())
slidingUpPanelLayout.expandPanel();
break;
}
}
};
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_player, container, false);
context = view.getContext();
mainView = view;
init(view);
return view;
}
private void init(View view) {
playerState = PlayerState.PAUSED;
miniController = view.findViewById(R.id.small_panel);
miniSongTitle = (TextView) view.findViewById(R.id.mini_player_song_name);
artHolder = (ImageView) mainView.findViewById(R.id.player_album_art);
utils = new Utils(context);
size = utils.getWindowWidth();
IntentFilter filter = new IntentFilter();
filter.addAction(PlayerFragment.ACTION_RECIEVE_SONG);
filter.addAction(ACTION_OPEN_PANEL);
getActivity().registerReceiver(br, filter);
setLargePlayer();
updateNavigationHeader(null);
}
private void updateNavigationHeader(Intent intent) {
if (navArt.getDrawable() == null || intent == null) {
navArt.setImageBitmap(utils.getBitmapOfVector(R.drawable.default_art,
size, size));
navTitle.setText(null);
navSubTitle.setText(null);
} else {
navTitle.setText(intent.getStringExtra("songName"));
navSubTitle.setText(intent.getStringExtra("albumName"));
}
}
private void setLargePlayer() {
preferenceHandler = new UserPreferenceHandler(context);
volumeSeekBar = (AppCompatSeekBar) mainView.findViewById(R.id.controls_volume_seekbar);
backButton = (ImageView) mainView.findViewById(R.id.player_back_button);
overflowMenu = (ImageView) mainView.findViewById(R.id.player_overflow_button);
currentSongHolder = (LinearLayout) mainView.findViewById(R.id.player_current_song);
next = (ImageView) mainView.findViewById(R.id.controller_next);
prev = (ImageView) mainView.findViewById(R.id.controller_prev);
pause = (ImageView) mainView.findViewById(R.id.controller_play);
repeat = (ImageView) mainView.findViewById(R.id.controller_repeat);
shuffle = (ImageView) mainView.findViewById(R.id.controller_shuffle);
controllHolder = (LinearLayout) mainView.findViewById(R.id.controller_holder);
noVolume = (ImageView) mainView.findViewById(R.id.controls_volume_icon_empty);
fullVolume = (ImageView) mainView.findViewById(R.id.controls_volume_icon_full);
waveIcon = (ImageView) mainView.findViewById(R.id.wave_large_player);
playlist = (ImageView) mainView.findViewById(R.id.playlist_large_player);
largeSongTitle = (TextView) mainView.findViewById(R.id.name_large_player);
seekBar = (AppCompatSeekBar) mainView.findViewById(R.id.control_seek_bar);
currentSeekText = (TextView) mainView.findViewById(R.id.controls_current_pos);
totalSeekText = (TextView) mainView.findViewById(R.id.controls_total_pos);
revealView = mainView.findViewById(R.id.player_reveal_view);
updateRepeat();
updateShuffle();
setVolumeControls();
setListeners();
askUpdate();
setControllerSize();
changeButtonColor();
setActionButtonClicks(backButton, overflowMenu);
handleStatusBarColor();
}
private void setVolumeControls() {
audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
MAX_VOL = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
int curVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
volumeSeekBar.setMax(MAX_VOL);
volumeSeekBar.setProgress(curVolume);
}
private void setListeners() {
overflowMenu.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
PopupMenu menu = new PopupMenu(context, view);
menu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.overflow_player_open_album:
Intent i = new Intent(context, AlbumActivity.class);
i.putExtra("albumName", currentSong.getAlbumName());
i.putExtra("albumId", currentSong.getAlbumId());
i.putExtra("albumColor", colorLight);
startActivity(i);
return true;
case R.id.overflow_player_open_artist:
Intent a = new Intent(context, ArtistActivity.class);
a.putExtra("name", currentSong.getArtist());
a.putExtra("id", ListSongs.getArtistIdFromName(context,
currentSong.getArtist()));
context.startActivity(a);
return true;
}
return false;
}
});
menu.inflate(R.menu.overflow_player);
menu.show();
}
});
artHolder.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (!slidingUpPanelLayout.isPanelExpanded())
slidingUpPanelLayout.expandPanel();
}
});
noVolume.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, 0, 0);
volumeSeekBar.setProgress(0);
}
});
fullVolume.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, MAX_VOL, 0);
volumeSeekBar.setProgress(MAX_VOL);
}
});
playlist.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
int[] loc = new int[2];
revealView.setBackgroundColor(colorLight);
playlist.getLocationOnScreen(loc);
DrawableCompat.setTint(backButton.getDrawable(), 0xff444d5d);
DrawableCompat.setTint(overflowMenu.getDrawable(), 0xff444d5d);
Animator anim = ViewAnimationUtils
.createCircularReveal(revealView, loc[0], loc[1], 0,
(new Utils(context).getWindowWidth()) * 2);
anim.setDuration(800);
anim.setInterpolator(new FastOutSlowInInterpolator());
revealView.setVisibility(View.VISIBLE);
anim.addListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {
}
@Override
public void onAnimationEnd(Animator animator) {
upNextFragment.setColorLight(colorLight);
upNextFragment.setSlidingUpPanelLayout(slidingUpPanelLayout);
getActivity().getSupportFragmentManager()
.beginTransaction().replace(R.id.panel_holder, upNextFragment)
.commit();
}
@Override
public void onAnimationCancel(Animator animator) {
}
@Override
public void onAnimationRepeat(Animator animator) {
}
});
anim.start();
}
});
volumeSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onStopTrackingTouch(SeekBar arg0) {
}
@Override
public void onStartTrackingTouch(SeekBar arg0) {
}
@Override
public void onProgressChanged(SeekBar arg0, int arg1, boolean arg2) {
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, arg1, 0);
}
});
controllHolder.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//to disable clicking
}
});
seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
Intent i = new Intent(PlayerService.ACTION_SEEK_SONG);
i.putExtra("seek", seekBar.getProgress());
context.sendBroadcast(i);
}
});
next.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
new Action() {
@NonNull
@Override
public String id() {
return TAG;
}
@Nullable
@Override
protected Object run() throws InterruptedException {
context.sendBroadcast(new Intent(PlayerService.ACTION_NEXT_SONG));
return null;
}
}.execute();
}
});
prev.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
new Action() {
@NonNull
@Override
public String id() {
return TAG;
}
@Nullable
@Override
protected Object run() throws InterruptedException {
context.sendBroadcast(new Intent(PlayerService.ACTION_PREV_SONG));
return null;
}
}.execute();
}
});
pause.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
context.sendBroadcast(new Intent(PlayerService.ACTION_PAUSE_SONG));
if (playerState == PlayerState.PLAYING)
pause();
else
play();
}
});
repeat.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
preferenceHandler.setRepeatEnable();
updateRepeat();
}
});
shuffle.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
preferenceHandler.setShuffle();
updateShuffle();
}
});
}
public void setMiniPlayerAlpha(int alpha) {
miniController.setAlpha(alpha);
}
private void updateRepeat() {
if (preferenceHandler.isRepeatAllEnabled()) {
repeat.getDrawable().setAlpha(MAX_ALPHA);
repeat.setImageDrawable(ContextCompat.getDrawable(context,
R.drawable.ic_repeat_white_48dp));
DrawableCompat.setTint(repeat.getDrawable(), colorTo);
} else if (preferenceHandler.isRepeatOneEnabled()) {
repeat.setImageDrawable(ContextCompat.getDrawable(context,
R.drawable.ic_repeat_one_white_48dp));
repeat.getDrawable().setAlpha(MAX_ALPHA);
DrawableCompat.setTint(repeat.getDrawable(), colorTo);
} else {
repeat.setImageDrawable(ContextCompat
.getDrawable(context, R.drawable.ic_repeat_white_48dp));
repeat.getDrawable().setAlpha(TRANS_ALPHA);
DrawableCompat.setTint(repeat.getDrawable(), colorTo);
}
}
private void play() {
playerState = PlayerState.PLAYING;
pause.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.ic_pause_white_48dp));
DrawableCompat.setTint(pause.getDrawable(), colorTo);
}
private void pause() {
playerState = PlayerState.PAUSED;
pause.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.ic_play_arrow_white_48dp));
DrawableCompat.setTint(pause.getDrawable(), colorTo);
}
private void updateShuffle() {
if (preferenceHandler.isShuffleEnabled()) {
shuffle.getDrawable().setAlpha(MAX_ALPHA);
} else
shuffle.getDrawable().setAlpha(TRANS_ALPHA);
}
public void onResume() {
super.onResume();
askUpdate();
}
private void askUpdate() {
Intent i = new Intent();
i.setAction(PlayerService.ACTION_GET_SONG);
context.sendBroadcast(i);
}
@Override
public void onDestroyView() {
super.onDestroyView();
context.unregisterReceiver(br);
}
private void setStatusBarColor(int color) {
((MainActivity) getActivity()).setStatusBarColor(color);
}
private void handleStatusBarColor() {
slidingUpPanelLayout.setPanelSlideListener(
new SlidingUpPanelLayout.PanelSlideListener() {
@Override
public void onPanelSlide(View panel, float slideOffset) {
if (slideOffset == 1 && colorLight != 0 && isVisible())
setStatusBarColor(colorDark);
else if (isVisible())
setStatusBarColor(ContextCompat.getColor(context, R.color.colorPrimaryDark));
View nowPlayingCard = PlayerFragment.miniController;
nowPlayingCard.setAlpha(1 - slideOffset);
}
@Override
public void onPanelCollapsed(View panel) {
View nowPlayingCard = PlayerFragment.miniController;
nowPlayingCard.setAlpha(1);
if (revealView.getVisibility() == View.VISIBLE) {
revealView.setVisibility(View.INVISIBLE);
DrawableCompat.setTint(backButton.getDrawable(), colorTo);
DrawableCompat.setTint(overflowMenu.getDrawable(), colorTo);
}
}
@Override
public void onPanelExpanded(View panel) {
View nowPlayingCard = PlayerFragment.miniController;
nowPlayingCard.setAlpha(0);
int curVolume = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
volumeSeekBar.setProgress(curVolume);
}
@Override
public void onPanelAnchored(View panel) {
}
@Override
public void onPanelHidden(View panel) {
}
});
}
private void setControllerSize() {
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(size, size);
artHolder.setLayoutParams(lp);
}
private void setActionButtonClicks(ImageView backButton, ImageView overflowMenu) {
backButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
slidingUpPanelLayout.collapsePanel();
}
});
overflowMenu.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
}
});
}
public void setSlidingUpPanelLayout(SlidingUpPanelLayout slidingUpPanelLayout) {
this.slidingUpPanelLayout = slidingUpPanelLayout;
}
private void changeButtonColor() {
DrawableCompat.setTint(backButton.getDrawable(), colorTo);
DrawableCompat.setTint(overflowMenu.getDrawable(), colorTo);
DrawableCompat.setTint(volumeSeekBar.getThumb(), colorTo);
DrawableCompat.setTint(volumeSeekBar.getProgressDrawable(), colorTo);
DrawableCompat.setTint(pause.getDrawable(), colorTo);
DrawableCompat.setTint(prev.getDrawable(), colorTo);
DrawableCompat.setTint(next.getDrawable(), colorTo);
DrawableCompat.setTint(shuffle.getDrawable(), colorTo);
DrawableCompat.setTint(repeat.getDrawable(), colorTo);
DrawableCompat.setTint(noVolume.getDrawable(), colorTo);
DrawableCompat.setTint(fullVolume.getDrawable(), colorTo);
DrawableCompat.setTint(playlist.getDrawable(), colorTo);
DrawableCompat.setTint(waveIcon.getDrawable(), colorTo);
DrawableCompat.setTint(volumeSeekBar.getProgressDrawable(), colorTo);
}
private void updatePlayer(Intent intent) {
String name = intent.getStringExtra("songName");
currentSong = new PlayerDBHandler(context)
.getSongFromId(intent.getLongExtra("songId", 0));
String path = ListSongs.getAlbumArt(context,
currentSong.getAlbumId());
updateMiniPlayer(name, path);
updateMainPlayer(intent, path);
updateNavigationHeader(intent);
}
private void updateMainPlayer(Intent intent, final String path) {
new Action() {
private Bitmap img;
@NonNull
@Override
public String id() {
return TAG;
}
@Override
protected void done(@Nullable Object result) {
if (path != null && (new File(path)).exists()) {
Picasso.with(context).load(new File(path)).resize(size, size)
.centerCrop().into(new Target() {
@Override
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
artHolder.setImageBitmap(bitmap);
navArt.setImageBitmap(bitmap);
}
@Override
public void onBitmapFailed(Drawable errorDrawable) {
}
@Override
public void onPrepareLoad(Drawable placeHolderDrawable) {
}
});
return;
}
artHolder.setImageBitmap(img);
navArt.setImageBitmap(img);
}
@Nullable
@Override
protected Object run() throws InterruptedException {
if (path != null && (new File(path)).exists()) {
return null;
} else {
img = utils.getBitmapOfVector(R.drawable.default_art,
size, size);
}
return null;
}
}.execute();
totalSeekText.setText(currentSong.getDuration());
seekBar.setMax((int) currentSong.getDurationLong());
seekBar.setProgress(intent.getIntExtra("seek", 0));
currentSeekText.setText(currentSong.getFormatedTime(
intent.getIntExtra("seek", 0)));
updateSeekBar();
}
private void updateSeekBar() {
if (timer == null) {
timer = new Timer();
TimerTask task = new TimerTask() {
@Override
public void run() {
((Activity) context).runOnUiThread(new Runnable() {
public void run() {
if (playerState == PlayerState.PLAYING) {
seekBar.setProgress(seekBar.getProgress() + 100);
currentSeekText.setText(currentSong.getFormatedTime(seekBar.getProgress()));
}
}
});
}
};
timer.schedule(task, 0, 100);
}
}
private void updateMiniPlayer(String name, String path) {
miniSongTitle.setText(name);
largeSongTitle.setText(name);
new ColorChangeAnimation(PlayerFragment.this.context, (LinearLayout) miniController,
miniSongTitle, (ImageView) mainView.findViewById(R.id.mini_player_img), path) {
@Override
public void onColorFetched(Palette palette, Integer colorPrimary) {
colorLight = palette.getVibrantColor(ContextCompat
.getColor(context, R.color.colorPrimary));
colorDark = getDarkColor(colorLight);
colorTo = 0xffffffff;
if (palette.getVibrantSwatch() != null)
colorTo = palette.getVibrantSwatch().getBodyTextColor();
if (slidingUpPanelLayout.isPanelExpanded()) {
setStatusBarColor(colorDark);
}
animateColorChangeView(controllHolder, colorLight);
animateColorChangeView(currentSongHolder, colorDark);
changeButtonColor();
largeSongTitle.setTextColor(colorTo);
currentSeekText.setTextColor(colorTo);
totalSeekText.setTextColor(colorTo);
}
}.execute();
}
private void animateColorChangeView(final LinearLayout ll, int color) {
ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(),
((ColorDrawable) ll.getBackground()).getColor(), color);
colorAnimation.setDuration(2000);
colorAnimation.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animator) {
ll.setBackgroundColor((Integer) animator.getAnimatedValue());
}
});
colorAnimation.start();
}
public int getDarkColor(int baseColor) {
float[] hsv = new float[3];
Color.colorToHSV(baseColor, hsv);
hsv[2] *= 0.78f;
return Color.HSVToColor(hsv);
}
public boolean onKeyEvent(KeyEvent event) {
boolean handled = false;
switch (event.getKeyCode()) {
case KeyEvent.KEYCODE_VOLUME_UP:
if (slidingUpPanelLayout.isPanelExpanded()) {
volumeSeekBar.setProgress(volumeSeekBar.getProgress() + 1);
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC,
volumeSeekBar.getProgress() + 1, 0);
handled = true;
}
break;
case KeyEvent.KEYCODE_VOLUME_DOWN:
if (slidingUpPanelLayout.isPanelExpanded()) {
volumeSeekBar.setProgress(volumeSeekBar.getProgress() - 1);
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC,
volumeSeekBar.getProgress() - 1, 0);
handled = true;
}
break;
}
return handled;
}
public void onBackPressed() {
if (isVisible())
slidingUpPanelLayout.collapsePanel();
}
@Override
public void onDestroy() {
super.onDestroy();
try {
getActivity().unregisterReceiver(br);
} catch (IllegalArgumentException e) {
e.printStackTrace();
}
}
public void setUpNextFragment(UpNextFragment upNextFragment) {
this.upNextFragment = upNextFragment;
}
public void setNavigationHeader(View navigationHeader) {
navArt = (ImageView) navigationHeader.findViewById(R.id.nav_header_img);
navTitle = (TextView) navigationHeader.findViewById(R.id.nav_header_title);
navSubTitle = (TextView) navigationHeader.findViewById(R.id.nav_header_album);
}
private enum PlayerState {
PLAYING, PAUSED
}
}