MusicPlayerActivity.java 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488
  1. package com.androidhive.musicplayer;
  2. import java.io.IOException;
  3. import java.util.ArrayList;
  4. import java.util.HashMap;
  5. import java.util.Random;
  6. import org.arkiwi.app.R;
  7. import org.arkiwi.app.activity.Viewer;
  8. import org.arkiwi.app.feed.FeedQuery;
  9. import org.arkiwi.app.rss.RssReader;
  10. import android.app.Activity;
  11. import android.content.Intent;
  12. import android.media.MediaPlayer;
  13. import android.media.MediaPlayer.OnCompletionListener;
  14. import android.os.Bundle;
  15. import android.os.Handler;
  16. import android.util.Log;
  17. import android.view.View;
  18. import android.view.WindowManager;
  19. import android.widget.ImageButton;
  20. import android.widget.SeekBar;
  21. import android.widget.TextView;
  22. import android.widget.Toast;
  23. public class MusicPlayerActivity extends Activity implements OnCompletionListener, SeekBar.OnSeekBarChangeListener {
  24. private final static String LOG_TAG = "MPA";
  25. private ImageButton btnPlay;
  26. private ImageButton btnForward;
  27. private ImageButton btnBackward;
  28. private ImageButton btnNext;
  29. private ImageButton btnPrevious;
  30. private ImageButton btnPlaylist;
  31. private ImageButton btnRepeat;
  32. private ImageButton btnShuffle;
  33. private SeekBar songProgressBar;
  34. private TextView songTitleLabel;
  35. private TextView songCurrentDurationLabel;
  36. private TextView songTotalDurationLabel;
  37. // Media Player
  38. private MediaPlayer mp;
  39. // Handler to update UI timer, progress bar etc,.
  40. private WindowManager.LayoutParams layout;
  41. private Handler mHandler = new Handler();
  42. private SongsManager songManager;
  43. private Utilities utils;
  44. private int seekForwardTime = 5000; // 5000 milliseconds
  45. private int seekBackwardTime = 5000; // 5000 milliseconds
  46. private int currentSongIndex = 0;
  47. private boolean isShuffle = false;
  48. private boolean isRepeat = false;
  49. private ArrayList<HashMap<String, String>> songsList = new ArrayList<HashMap<String, String>>();
  50. @Override
  51. public void onCreate(Bundle savedInstanceState) {
  52. super.onCreate(savedInstanceState);
  53. setContentView(R.layout.pl_player);
  54. layout = getWindow().getAttributes();
  55. Log.d(LOG_TAG, "onCreate()");
  56. // All player buttons
  57. btnPlay = (ImageButton) findViewById(R.id.btnPlay);
  58. btnForward = (ImageButton) findViewById(R.id.btnForward);
  59. btnBackward = (ImageButton) findViewById(R.id.btnBackward);
  60. btnNext = (ImageButton) findViewById(R.id.btnNext);
  61. btnPrevious = (ImageButton) findViewById(R.id.btnPrevious);
  62. btnPlaylist = (ImageButton) findViewById(R.id.btnPlaylist);
  63. btnRepeat = (ImageButton) findViewById(R.id.btnRepeat);
  64. btnShuffle = (ImageButton) findViewById(R.id.btnShuffle);
  65. songProgressBar = (SeekBar) findViewById(R.id.songProgressBar);
  66. songTitleLabel = (TextView) findViewById(R.id.songTitle);
  67. songCurrentDurationLabel = (TextView) findViewById(R.id.songCurrentDurationLabel);
  68. songTotalDurationLabel = (TextView) findViewById(R.id.songTotalDurationLabel);
  69. Bundle extras = getIntent().getExtras();
  70. if(extras != null) {
  71. //tpe = (ThreadPoolExecutor) Executors.newSingleThreadExecutor();
  72. //mUpdateTimeTaskHandler = tpe.submit(mUpdateTimeTask);
  73. RssReader rssReader = RssReader.getInstance();
  74. FeedQuery fq = rssReader.getFeedQuery();
  75. //Mediaplayer
  76. mp = new MediaPlayer();
  77. songManager = SongsManager.getInstance();
  78. if(songManager.getSongsList().size()>0)
  79. songManager.getSongsList().clear();
  80. utils = new Utilities();
  81. // Listeners
  82. songProgressBar.setOnSeekBarChangeListener(this); // Important
  83. mp.setOnCompletionListener(this); // Important
  84. if(extras.getInt("type") == Viewer.MENU_XSPF_ID ) {
  85. //TODO: verificare se ho almeno 1 feeditem, è meglio
  86. //verificare prima di mandare l'intent... da vedere se
  87. //è fattibile.
  88. songsList = songManager.getPlayListFromWeb(
  89. fq.getFeedItems(getString(R.string.rss_type_audio)));
  90. } else if(extras.getInt("type") == Viewer.INTENT_SONG_ID){
  91. String key = extras.getString("feed");
  92. songsList = songManager.getPlayListFromWeb(
  93. fq.getFeedItem(fq.getFeedItem(key)));
  94. }
  95. if(songManager.getSongsList().size()>0)
  96. playSong(0);
  97. }
  98. /**
  99. * Play button click event
  100. * plays a song and changes button to pause image
  101. * pauses a song and changes button to play image
  102. * */
  103. btnPlay.setOnClickListener(new View.OnClickListener() {
  104. @Override
  105. public void onClick(View arg0) {
  106. if(resumeSong()){
  107. mp.pause();
  108. // Changing button image to play button
  109. btnPlay.setImageResource(R.drawable.pl_play);
  110. }
  111. }
  112. });
  113. /**
  114. * Forward button click event
  115. * Forwards song specified seconds
  116. * */
  117. btnForward.setOnClickListener(new View.OnClickListener() {
  118. @Override
  119. public void onClick(View arg0) {
  120. // get current song position
  121. int currentPosition = mp.getCurrentPosition();
  122. // check if seekForward time is lesser than song duration
  123. if(currentPosition + seekForwardTime <= mp.getDuration()){
  124. // forward song
  125. mp.seekTo(currentPosition + seekForwardTime);
  126. }else{
  127. // forward to end position
  128. mp.seekTo(mp.getDuration());
  129. }
  130. }
  131. });
  132. /**
  133. * Backward button click event
  134. * Backward song to specified seconds
  135. * */
  136. btnBackward.setOnClickListener(new View.OnClickListener() {
  137. @Override
  138. public void onClick(View arg0) {
  139. // get current song position
  140. int currentPosition = mp.getCurrentPosition();
  141. // check if seekBackward time is greater than 0 sec
  142. if(currentPosition - seekBackwardTime >= 0){
  143. // forward song
  144. mp.seekTo(currentPosition - seekBackwardTime);
  145. }else{
  146. // backward to starting position
  147. mp.seekTo(0);
  148. }
  149. }
  150. });
  151. /**
  152. * Next button click event
  153. * Plays next song by taking currentSongIndex + 1
  154. * */
  155. btnNext.setOnClickListener(new View.OnClickListener() {
  156. @Override
  157. public void onClick(View arg0) {
  158. Log.d(LOG_TAG, "btnNext() "+currentSongIndex);
  159. // check if next song is there or not
  160. if(currentSongIndex < (songsList.size() - 1)){
  161. playSong(currentSongIndex + 1);
  162. currentSongIndex = currentSongIndex + 1;
  163. }else{
  164. // play first song
  165. playSong(0);
  166. currentSongIndex = 0;
  167. Toast.makeText(getApplicationContext(), R.string.toast_pl_no_next, Toast.LENGTH_SHORT).show();
  168. }
  169. }
  170. });
  171. /**
  172. * Back button click event
  173. * Plays previous song by currentSongIndex - 1
  174. * */
  175. btnPrevious.setOnClickListener(new View.OnClickListener() {
  176. @Override
  177. public void onClick(View arg0) {
  178. Log.d(LOG_TAG, "btnPrevious() "+currentSongIndex);
  179. if(currentSongIndex > 0){
  180. playSong(currentSongIndex - 1);
  181. currentSongIndex = currentSongIndex - 1;
  182. }else{
  183. // play last song
  184. playSong(songsList.size() - 1);
  185. currentSongIndex = songsList.size() - 1;
  186. Toast.makeText(getApplicationContext(), R.string.toast_pl_no_prev, Toast.LENGTH_SHORT).show();
  187. }
  188. }
  189. });
  190. /**
  191. * Button Click event for Repeat button
  192. * Enables repeat flag to true
  193. * */
  194. btnRepeat.setOnClickListener(new View.OnClickListener() {
  195. @Override
  196. public void onClick(View arg0) {
  197. if(isRepeat){
  198. isRepeat = false;
  199. Toast.makeText(getApplicationContext(), R.string.toast_pl_r_off, Toast.LENGTH_SHORT).show();
  200. btnRepeat.setImageResource(R.drawable.pl_repeat);
  201. }else{
  202. // make repeat to true
  203. isRepeat = true;
  204. Toast.makeText(getApplicationContext(), R.string.toast_pl_r_on, Toast.LENGTH_SHORT).show();
  205. // make shuffle to false
  206. isShuffle = false;
  207. btnRepeat.setImageResource(R.drawable.pl_repeat_focused);
  208. btnShuffle.setImageResource(R.drawable.pl_shuffle);
  209. }
  210. }
  211. });
  212. /**
  213. * Button Click event for Shuffle button
  214. * Enables shuffle flag to true
  215. * */
  216. btnShuffle.setOnClickListener(new View.OnClickListener() {
  217. @Override
  218. public void onClick(View arg0) {
  219. if(isShuffle){
  220. isShuffle = false;
  221. Toast.makeText(getApplicationContext(), R.string.toast_pl_s_off, Toast.LENGTH_SHORT).show();
  222. btnShuffle.setImageResource(R.drawable.pl_shuffle);
  223. }else{
  224. // make repeat to true
  225. isShuffle= true;
  226. Toast.makeText(getApplicationContext(), R.string.toast_pl_s_on, Toast.LENGTH_SHORT).show();
  227. // make shuffle to false
  228. isRepeat = false;
  229. btnShuffle.setImageResource(R.drawable.pl_shuffle_focused);
  230. btnRepeat.setImageResource(R.drawable.pl_repeat);
  231. }
  232. }
  233. });
  234. /**
  235. * Button Click event for Play list click event
  236. * Launches list activity which displays list of songs
  237. * */
  238. btnPlaylist.setOnClickListener(new View.OnClickListener() {
  239. @Override
  240. public void onClick(View arg0) {
  241. layout.screenBrightness = -1;
  242. getWindow().setAttributes(layout);
  243. Intent i = new Intent(getApplicationContext(), PlayListActivity.class);
  244. startActivityForResult(i, 100);
  245. }
  246. });
  247. }
  248. @Override
  249. protected void onResume() {
  250. super.onResume();
  251. resumeSong();
  252. }
  253. /**
  254. * Se il brano è interrotto viene rimesso in play aggiornando il bottone
  255. */
  256. private boolean resumeSong(){
  257. boolean playng=false;
  258. if(mp != null) {
  259. if(! mp.isPlaying()){
  260. // Resume song
  261. mp.start();
  262. // Changing button image to pause button
  263. btnPlay.setImageResource(R.drawable.pl_pause);
  264. } else {
  265. playng=true;
  266. }
  267. layout.screenBrightness = 0.1f;
  268. getWindow().setAttributes(layout);
  269. }
  270. return playng;
  271. }
  272. /**
  273. * Receiving song index from playlist view
  274. * and play the song
  275. * */
  276. @Override
  277. protected void onActivityResult(int requestCode,
  278. int resultCode, Intent data) {
  279. super.onActivityResult(requestCode, resultCode, data);
  280. if(resultCode == 100){
  281. currentSongIndex = data.getExtras().getInt("songIndex");
  282. Log.d(LOG_TAG, "onActivityResult(), dalla playlist "+currentSongIndex);
  283. // play selected song
  284. playSong(currentSongIndex);
  285. }
  286. }
  287. /**
  288. * Function to play a song
  289. * @param songIndex - index of song
  290. * */
  291. public void playSong(int songIndex){
  292. // Play song
  293. try {
  294. Log.d(LOG_TAG, "playSong() "+songIndex);
  295. layout.screenBrightness = 0.1f;
  296. getWindow().setAttributes(layout);
  297. mp.reset();
  298. mp.setDataSource(songsList.get(songIndex).get("songPath"));
  299. mp.prepare();
  300. mp.start();
  301. // Displaying Song title
  302. String songTitle = songsList.get(songIndex).get("songTitle");
  303. songTitleLabel.setText(songTitle);
  304. // Changing Button Image to pause image
  305. btnPlay.setImageResource(R.drawable.pl_pause);
  306. // set Progress bar values
  307. songProgressBar.setProgress(0);
  308. songProgressBar.setMax(100);
  309. // Updating progress bar
  310. updateProgressBar();
  311. } catch (IllegalArgumentException e) {
  312. e.printStackTrace();
  313. } catch (IllegalStateException e) {
  314. e.printStackTrace();
  315. } catch (IOException e) {
  316. e.printStackTrace();
  317. }
  318. }
  319. //TODO: gestirlo con un servizio così da non fermare la musica girando per l'app
  320. /**
  321. * Background Runnable thread
  322. * */
  323. private Runnable mUpdateTimeTask = new Runnable() {
  324. public void run() {
  325. long totalDuration = mp.getDuration();
  326. long currentDuration = mp.getCurrentPosition();
  327. // Displaying Total Duration time
  328. songTotalDurationLabel.setText(""+utils.milliSecondsToTimer(totalDuration));
  329. // Displaying time completed playing
  330. songCurrentDurationLabel.setText(""+utils.milliSecondsToTimer(currentDuration));
  331. // Updating progress bar
  332. int progress = (int)(utils.getProgressPercentage(currentDuration, totalDuration));
  333. //Log.d("Progress", ""+progress);
  334. songProgressBar.setProgress(progress);
  335. // Running this thread after 100 milliseconds
  336. mHandler.postDelayed(this, 100);
  337. }
  338. };
  339. /**
  340. *
  341. * */
  342. @Override
  343. public void onProgressChanged(SeekBar seekBar, int progress, boolean fromTouch) {}
  344. /**
  345. * Update timer on seekbar
  346. * */
  347. public void updateProgressBar() {
  348. mHandler.postDelayed(mUpdateTimeTask, 100);
  349. }
  350. /**
  351. * When user starts moving the progress handler
  352. * */
  353. @Override
  354. public void onStartTrackingTouch(SeekBar seekBar) {
  355. // remove message Handler from updating progress bar
  356. mHandler.removeCallbacks(mUpdateTimeTask);
  357. }
  358. /**
  359. * When user stops moving the progress hanlder
  360. * */
  361. @Override
  362. public void onStopTrackingTouch(SeekBar seekBar) {
  363. mHandler.removeCallbacks(mUpdateTimeTask);
  364. int totalDuration = mp.getDuration();
  365. int currentPosition = utils.progressToTimer(seekBar.getProgress(), totalDuration);
  366. // forward or backward to certain seconds
  367. mp.seekTo(currentPosition);
  368. // update timer progress again
  369. updateProgressBar();
  370. }
  371. /**
  372. * On Song Playing completed
  373. * if repeat is ON play same song again
  374. * if shuffle is ON play random song
  375. * */
  376. @Override
  377. public void onCompletion(MediaPlayer arg0) {
  378. // check for repeat is ON or OFF
  379. if(isRepeat){
  380. // repeat is on play same song again
  381. playSong(currentSongIndex);
  382. } else if(isShuffle){
  383. // shuffle is on - play a random song
  384. Random rand = new Random();
  385. currentSongIndex = rand.nextInt((songsList.size() - 1) - 0 + 1) + 0;
  386. playSong(currentSongIndex);
  387. } else{
  388. //TODO:se ci sono solo poche tracce continua a ciclare,
  389. //essendo che le tracce le prende da internet, forse è meglio
  390. //fermarlo?
  391. // no repeat or shuffle ON - play next song
  392. if(currentSongIndex < (songsList.size() - 1)){
  393. playSong(currentSongIndex + 1);
  394. currentSongIndex = currentSongIndex + 1;
  395. }else{
  396. // play first song
  397. playSong(0);
  398. currentSongIndex = 0;
  399. }
  400. }
  401. }
  402. @Override
  403. protected void onPause() {
  404. super.onPause();
  405. if(mp != null) {
  406. if(mp.isPlaying()){
  407. mp.pause();
  408. layout.screenBrightness = -1;
  409. getWindow().setAttributes(layout);
  410. }
  411. }
  412. }
  413. @Override
  414. public void onDestroy(){
  415. Log.d(LOG_TAG, "onDestroy()");
  416. super.onDestroy();
  417. layout.screenBrightness = -1;
  418. getWindow().setAttributes(layout);
  419. if(mp != null) {
  420. mHandler.removeCallbacks(mUpdateTimeTask);
  421. mp.release();
  422. }
  423. }
  424. }