app:前端
com.example.honl.muiscocojava
resandroid
音樂播放器使用的媒體類是內置的媒體類下面代碼是使用cursor用於從數據庫中查詢歌曲的信息,保存在List當中數據庫
public static ArrayList<Mp3Info> getMp3Infos(Context context) { System.out.println("MediaUtils.java #2 : " + MediaStore.Audio.Media.EXTERNAL_CONTENT_URI); Cursor cursor = context.getContentResolver().query( MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, null, MediaStore.Audio.Media.DURATION + ">=10000", null, MediaStore.Audio.Media.DEFAULT_SORT_ORDER); ArrayList<Mp3Info> mp3Infos = new ArrayList<Mp3Info>(); System.out.println("MediaUtils.java #3 :cursor.getCount() : " + cursor.getCount()); for (int i = 0; i < cursor.getCount(); i++) { cursor.moveToNext(); Mp3Info mp3Info = new Mp3Info(); long id = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media._ID));//音樂id String title = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.TITLE));//音樂標題 String artist = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ARTIST));//藝術家 String album = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM));//專輯 long albumid = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID));//專輯id long duration = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.DURATION));//時長 long size = cursor.getLong(cursor.getColumnIndex(MediaStore.Audio.Media.SIZE));//文件大小 String url = cursor.getString(cursor.getColumnIndex(MediaStore.Audio.Media.DATA));//文件路徑 int isMusic = cursor.getInt(cursor.getColumnIndex(MediaStore.Audio.Media.IS_MUSIC));//是否爲音樂 if (isMusic != 0) { mp3Info.setId(id); mp3Info.setTitle(title); mp3Info.setArtist(artist); mp3Info.setAlbum(album); mp3Info.setAlbumId(albumid); mp3Info.setDuration(duration); mp3Info.setSize(size); mp3Info.setUrl(url); mp3Infos.add(mp3Info); System.out.println("MediaUtils.java #401 : title = " + title + " | artist = " + artist + " | duration = " + duration); System.out.println("MediaUtils.java #402 : id = " + id + " | album = " + album + " | size = " + size); System.out.println("MediaUtils.java #403 : url = " + url); System.out.println("MediaUtils.java #404 : mp3Infos = " + mp3Infos.size()); System.out.println("MediaUtils.java #405 : mp3islove = " + mp3Info.getIsLove()); } } cursor.close(); System.out.println("MediaUtils.java #405 : mp3Infos = " + mp3Infos.size()); return mp3Infos; }
經過數據庫中albumId來得到媒體封面app
public static Bitmap loadCoverFromMediaStore(Context context,long albumId) { ContentResolver resolver = context.getContentResolver(); Uri albumUri = ContentUris.withAppendedId(Uri.parse("content://media/external/audio/albumart"), albumId); InputStream is; try { is = resolver.openInputStream(albumUri); } catch (FileNotFoundException ignored) { return null; } BitmapFactory.Options options = new BitmapFactory.Options(); options.inPreferredConfig = Bitmap.Config.RGB_565; return BitmapFactory.decodeStream(is, null, options); }
由於播放器切換音樂時候涉及不斷切換後臺服務和前端UI,BaseActivity和PlayService是音樂播放器的基礎,之中提供和實現了更新UI和更新音樂信息的接口。ide
在BaseActivity中提供兩個抽象類來用來更新音樂,UI佈局
public abstract void publish(int progress); public abstract void change(int progress);
在BaseActivity基礎之上,創建了PlayActivity和MainActivity類。音樂的播放信息,好比播放位置、播放模式、是否收藏都須要活動與服務之間通訊。測試
//綁定service private ServiceConnection conn = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { PlayService.PlayBinder playBinder = (PlayService.PlayBinder) service; playService = playBinder.getPlayService(); playService.setMusicUpdateListener(musicUpdateListener); musicUpdateListener.onChange(playService.getCurrentPosition()); } @Override public void onServiceDisconnected(ComponentName name) { playService = null; isBound = false; } }; //綁定服務 public void bindPlayService() { if (isBound == false) { Intent bindintent = new Intent(this, PlayService.class); bindService(bindintent, conn, Context.BIND_AUTO_CREATE);//綁定服務 System.out.println("我已經綁定"); isBound = true; } } //解綁服務 public void unbindPlayService() { if (isBound == true) { unbindService(conn); System.out.println("鬆綁了"); isBound = false; } }
在PlayService中提供一個接口用來更新音樂,UI動畫
public interface MusicUpdateListener { public void onPublish(int progress); public void onChange(int position); }
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent"> <LinearLayout android:id="@+id/linearLayout3" android:layout_width="match_parent" android:layout_height="50dp" android:layout_margin="0dp"> <TextView android:id="@+id/main_myMusic" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:text="本地音樂" android:textSize="20sp" /> <TextView android:id="@+id/main_myRecord" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center" android:text="個人歌單" android:textSize="20sp" /> </LinearLayout> <android.support.v4.view.ViewPager android:id="@+id/pager" android:layout_width="match_parent" android:layout_height="wrap_content" tools:context=".MainActivity" /> </RelativeLayout>
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> //設置背景圖片 <ImageView android:id="@+id/listen_background_iv" android:layout_width="match_parent" android:layout_height="match_parent" android:scaleType="centerCrop" /> //設置唱片圓盤 <ImageView android:id="@+id/imageView1_ablum" android:layout_width="250dp" android:layout_height="250dp" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:src="@mipmap/default_cover" /> //設置圓盤上的指針 <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_alignParentLeft="true" android:layout_alignParentTop="true" android:layout_marginLeft="0dp" android:layout_marginTop="0dp" android:layout_marginBottom="15dp"> <RelativeLayout android:id="@+id/listen_play" android:layout_width="match_parent" android:layout_height="60dp" android:layout_alignParentBottom="true" android:layout_marginBottom="0dp"> //設置收藏 <ImageView android:id="@+id/play_activity_myLove" android:layout_width="40dp" android:layout_height="40dp" android:layout_centerVertical="true" android:layout_marginLeft="30dp" android:layout_marginRight="30dp" android:src="@mipmap/heart_fill" /> //設置「上一首」 <ImageView android:id="@+id/imageView3_previous" android:layout_width="40dp" android:layout_height="40dp" android:layout_centerVertical="true" android:layout_marginLeft="30dp" android:layout_marginRight="30dp" android:layout_toLeftOf="@id/imageView2_play_pause" android:src="@mipmap/back_w" /> //設置「暫停」 <ImageView android:id="@+id/imageView2_play_pause" android:layout_width="50dp" android:layout_height="50dp" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:src="@mipmap/play_circle" /> //設置下一首 <ImageView android:id="@+id/imageView1_next" android:layout_width="40dp" android:layout_height="40dp" android:layout_centerVertical="true" android:layout_marginLeft="30dp" android:layout_toRightOf="@id/imageView2_play_pause" android:src="@mipmap/next_w" /> //設置播放模式 <ImageView android:id="@+id/imageView1_play_mode" android:layout_width="40dp" android:layout_height="40dp" android:layout_alignParentTop="true" android:layout_alignParentEnd="true" android:layout_marginTop="10dp" android:layout_toEndOf="@+id/imageView1_next" android:src="@mipmap/single_play" /> </RelativeLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_above="@id/listen_play" android:layout_marginBottom="10dp" android:orientation="horizontal" android:paddingLeft="10dp" android:paddingRight="10dp"> //設置「當前歌曲時間」 <TextView android:id="@+id/textView1_start_time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="00:00" /> //設置「進度條」 <SeekBar android:id="@+id/seekBar1" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" /> //設置「歌曲總時長」 <TextView android:id="@+id/textView1_end_time" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="02:30" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="90dp" android:gravity="center_horizontal" android:orientation="vertical"> //android:background="@color/colorAccent" <TextView android:id="@+id/msc_title" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="center" android:clickable="true" android:ellipsize="marquee" android:focusable="true" android:focusableInTouchMode="true" android:hapticFeedbackEnabled="true" android:marqueeRepeatLimit="marquee_forever" android:maxWidth="250dp" android:singleLine="true" android:text="爲了測試單行文字滾動而取的長歌名" android:textColor="#333333" android:textSize="30dp" /> <TextView android:id="@+id/msc_artist" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_marginTop="10dp" android:text="石進" android:textColor="#333333" android:textSize="20dp" /> </LinearLayout> </RelativeLayout> </RelativeLayout>
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".SplashActivity"> <Button android:id="@+id/skip" android:layout_width="84dp" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:layout_marginEnd="8dp" android:layout_marginBottom="16dp" android:text="跳過" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.915" app:layout_constraintStart_toStartOf="parent" /> <TextView android:id="@+id/textView2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:layout_marginTop="200dp" android:layout_marginEnd="8dp" android:text="@string/lxq" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/textView3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:layout_marginTop="8dp" android:layout_marginEnd="8dp" android:layout_marginBottom="8dp" android:text="@string/zhy" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/textView2" app:layout_constraintVertical_bias="0.05" /> <TextView android:id="@+id/textView4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:layout_marginTop="8dp" android:layout_marginEnd="8dp" android:layout_marginBottom="8dp" android:text="@string/ycx" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/textView3" app:layout_constraintVertical_bias="0.05" /> <Button android:id="@+id/btn2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="100dp" android:layout_marginEnd="8dp" android:text="顯示學號" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.479" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/textView4" /> </android.support.constraint.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/frameLayout" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@android:color/background_light" tools:context=".bottomInfoFr"> <LinearLayout android:id="@+id/bottom_info_duration" android:layout_width="match_parent" android:layout_height="46dp" android:orientation="horizontal" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toBottomOf="@+id/bottom_info_title"> <TextView android:id="@+id/left_durationi" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center_vertical" android:paddingLeft="10dp" android:text="播放時長" /> <TextView android:id="@+id/right_duration" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="3" android:gravity="center_vertical" android:text="TextView" /> </LinearLayout> <LinearLayout android:id="@+id/bottom_info_title" android:layout_width="match_parent" android:layout_height="46dp" android:orientation="horizontal" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintVertical_bias="0.0"> <TextView android:id="@+id/left_title" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center_vertical" android:paddingLeft="10dp" android:text="文件名稱" /> <TextView android:id="@+id/right_title" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="3" android:gravity="center_vertical" android:text="TextView" /> </LinearLayout> <LinearLayout android:id="@+id/bottom_info_url" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" android:paddingBottom="10dp" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toBottomOf="@+id/bottom_info_size"> <TextView android:id="@+id/left_url" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center_vertical" android:paddingLeft="10dp" android:text="文件路徑" /> <TextView android:id="@+id/right_url" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="3" android:gravity="center_vertical" /> </LinearLayout> <LinearLayout android:id="@+id/bottom_info_size" android:layout_width="match_parent" android:layout_height="46dp" android:orientation="horizontal" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toBottomOf="@+id/bottom_info_artist"> <TextView android:id="@+id/left_size" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center_vertical" android:paddingLeft="10dp" android:text="文件大小" /> <TextView android:id="@+id/right_size" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="3" android:gravity="center_vertical" /> </LinearLayout> <LinearLayout android:id="@+id/bottom_info_artist" android:layout_width="match_parent" android:layout_height="46dp" android:orientation="horizontal" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toBottomOf="@+id/bottom_info_duration"> <TextView android:id="@+id/left_artist" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center_vertical" android:paddingLeft="10dp" android:text="歌手名稱" /> <TextView android:id="@+id/right_artist" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="3" android:gravity="center_vertical" /> </LinearLayout> </android.support.constraint.ConstraintLayout>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas. android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MyMusicListFragment" app:layout_editor_absoluteY="81dp"> <ListView android:id="@+id/listView_my_music" android:layout_width="wrap_content" android:layout_height="420dp" android:layout_marginLeft="8dp" android:layout_marginEnd="8dp" android:visibility="visible" app:layout_constraintBottom_toTopOf="@+id/listen_rl" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <RelativeLayout android:id="@+id/listen_rl" android:layout_width="match_parent" android:layout_height="70dp" app:layout_constraintBottom_toBottomOf="parent" tools:layout_editor_absoluteX="0dp"> //設置佈局間的分割線 <View android:layout_width="match_parent" android:layout_height="0.5dp" android:background="#bababa" /> //設置封面 <ImageView android:id="@+id/listen_cover_iv" android:layout_width="60dp" android:layout_height="60dp" android:layout_alignParentLeft="true" android:layout_centerVertical="true" android:layout_marginLeft="5dp" android:src="@mipmap/back1" /> //設置歌曲名 <TextView android:id="@+id/listen_title_tv" android:layout_width="wrap_content" android:maxWidth="140dp" android:ellipsize="end" android:singleLine="true" android:layout_height="wrap_content" android:layout_marginLeft="15dp" android:layout_marginTop="8dp" android:layout_toRightOf="@id/listen_cover_iv" android:text="xxx" android:textColor="#aeabab" android:textSize="20sp" /> //設置歌手名 <TextView android:id="@+id/listen_artist_tv" android:layout_width="100dp" android:layout_height="wrap_content" android:layout_below="@id/listen_title_tv" android:layout_alignLeft="@id/listen_title_tv" android:layout_gravity="center" android:layout_marginTop="5dp" android:clickable="true" android:ellipsize="marquee" android:focusable="true" android:focusableInTouchMode="true" android:marqueeRepeatLimit="marquee_forever" android:singleLine="true" android:textColor="#aeabab" android:textSize="15sp" /> //設置專輯名 <TextView android:id="@+id/listen_album_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignTop="@id/listen_artist_tv" android:layout_toRightOf="@id/listen_artist_tv" android:textColor="#aeabab" android:textSize="15sp" /> //設置播放暫停 <ImageView android:id="@+id/playmusic" android:layout_width="30dp" android:layout_height="30dp" android:layout_toRightOf="@id/listen_album_tv" android:layout_marginLeft="50dp" android:layout_centerVertical="true" android:src="@mipmap/play_circle" /> <!--android:layout_alignParentRight="true"--> <!--android:layout_marginRight="63dp"--> //設置收藏 <ImageView android:id="@+id/mylove" android:layout_width="30dp" android:layout_height="30dp" android:layout_toRightOf="@id/playmusic" android:layout_centerVertical="true" android:src="@mipmap/heart_fill" /> <!--android:layout_alignParentRight="true"--> <!--android:layout_marginRight="15dp"--> </RelativeLayout> </android.support.constraint.ConstraintLayout>
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> //運用相對佈局文件 <RelativeLayout android:layout_width="match_parent" android:layout_height="50dp" android:orientation="vertical" android:gravity="center" android:layout_gravity="center" > //建立列表歌曲間的橫線 <View android:id="@+id/list_column_v" android:layout_width="0.5dp" android:layout_height="match_parent" android:visibility="visible" ></View> //設置專輯圖片樣式 <ImageView android:id="@+id/simple_cover_Iv" android:layout_width="50dp" android:layout_height="50dp" android:layout_alignBottom="@+id/linearLayout" android:layout_marginLeft="11dp" android:layout_toRightOf="@+id/list_column_v" android:src="@mipmap/default_cover" /> //運行線性佈局文件進行TextView佈局 <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toRightOf="@id/simple_cover_Iv" android:orientation="vertical" android:layout_marginTop="5dp" android:layout_marginLeft="5dp" android:id="@+id/linearLayout"> //建立歌曲名佈局代碼 <TextView android:id="@+id/textView1_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Something just like this" /> //建立歌曲專輯及做者名代碼 <TextView android:id="@+id/textView2_singer" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="5dp" android:text="Cold Player/The Chainsmokers" /> </LinearLayout> //建立「更多選項」圖片 <ImageView android:id="@+id/simple_more_iv" android:layout_width="50dp" android:layout_height="20dp" android:layout_marginTop="10dp" android:layout_marginBottom="10dp" android:layout_alignParentEnd="true" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:src="@mipmap/ic_music_list_icon_more" /> </RelativeLayout> </LinearLayout>
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:tools="http://schemas.android.com/tools"> <LinearLayout android:id="@+id/linearLayout4" android:layout_width="match_parent" android:layout_height="555dp" android:orientation="vertical" app:layout_constraintBottom_toBottomOf="parent" > <ListView android:id="@+id/sp_listview" android:layout_width="match_parent" android:layout_height="wrap_content" tools:context=".MainActivity" /> </LinearLayout> <android.support.design.widget.FloatingActionButton android:id="@+id/fab" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="bottom|end" android:layout_margin="@dimen/fab_margin" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintRight_toRightOf="parent" /> </android.support.constraint.ConstraintLayout>