이번에 작업해볼 내용은 mp3파일 플레이어를 service로 구동하여 볼것입니다.
service를 이용하여 mp3파일을 실행시키기 위해서는 service 부분에서 mp3파일을 받아야
하며 mp3플레이어인 MediaPlayer 가 service에 생성되어야 합니다.
이전 포스트에서 제가 MusicData의 소스를 공개를 안했군요..
이전 처럼 소스를 공개 안했을 상황이 생기는거 같아서 전체적으로 Notification을 이용하는
방법 까지 다 구현하겠습니다.
1. MusicData 입니다.
버튼을 클릭하였을 경우 Intent로 서비스에 음악 데이터를 넘겨줘야하는데 차후 Notification
을 띄어서 음악을 변경하는 등의 작업을 하여야 하므로 intent값에 array를 넣어야 하는데 안
드로이드에서는 array값을 intent에 담에서 넘길때는 조금 특별한 작업을 해줘야 합니다. 그
작업은 아래와 같습니다.
public class MusicData implements Parcelable{ private String musicTitle; private String singer; private Uri musicImg; private String albumId; private String musicId; public String getMusicTitle() { return musicTitle; } public void setMusicTitle(String musicTitle) { this.musicTitle = musicTitle; } public String getSinger() { return singer; } public void setSinger(String singer) { this.singer = singer; } public Uri getMusicImg() { return musicImg; } public void setMusicImg(Uri musicImg) { this.musicImg = musicImg; } public String getAlbumId() { return albumId; } public void setAlbumId(String albumId) { this.albumId = albumId; } public String getMusicId() { return musicId; } public void setMusicId(String musicId) { this.musicId = musicId; } @Override public void writeToParcel(Parcel parcel, int i) { parcel.writeString(musicId); parcel.writeString(albumId); parcel.writeString(musicImg.toString()); parcel.writeString(musicTitle); parcel.writeString(singer); } @Override public int describeContents() { return 0; } public MusicData() { } public MusicData(Parcel in) { readFromParcel(in); } private void readFromParcel(Parcel in){ musicId = in.readString(); albumId = in.readString(); musicImg = Uri.parse(in.readString()); musicTitle = in.readString(); singer = in.readString(); } public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { public MusicData createFromParcel(Parcel in) { return new MusicData(in); } public MusicData[] newArray(int size) { return new MusicData[size]; } }; }
2. 그리고 이제 버튼을 클릭하였을경우 음악을 실행하여야 합니다.
Activity에서 Service를 실행시켜주는 Intent만 날려주면 되는데 이전에 혹시 제가 빼먹은게
있는거 같아서 전문 다 올리도록 하겠습니다. ListenMusic 함수가 Service 실행하는 함수입니다.
public class MusicServiceActivity extends Activity implements AdapterView.OnItemClickListener{ private String TAG = "MusicServiceActivity"; private Context mContext; private ListView musicListView; private MusicAdapter adapter; ArrayList<MusicData> list = new ArrayList<>(); private serviceReceiver receiver; @Override protected void onDestroy() { super.onDestroy(); Log.e(TAG, "MusicServiceActivity onDestroy"); unregisterReceiver(receiver); } @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_music); mContext = MusicServiceActivity.this; init(); getMusicData(); IntentFilter filter = new IntentFilter(MusicService.MUSIC_SERVICE_FILTER); receiver = new serviceReceiver(); registerReceiver(receiver, filter); } private void init(){ adapter = new MusicAdapter(mContext, android.R.layout.simple_list_item_1, list); adapter.setMusicBtnListener(new MusicAdapter.btnClickListener() { @Override public void MusicBtnClick(int position) { ListenMusic(position); } }); musicListView = findViewById(R.id.menuList); musicListView.setAdapter(adapter); musicListView.setOnItemClickListener(this); } private void getMusicData(){ //1. 음악파일인지 아닌지, 2. 앨범 아이디, 3. 음원명, 4.가수명, 미디어 파일 아이디(?) String[] projection = { MediaStore.Audio.Media.IS_MUSIC, MediaStore.Audio.Media.ALBUM_ID, MediaStore.Audio.Media.TITLE, MediaStore.Audio.Media.ARTIST, MediaStore.Audio.Media._ID}; ContentResolver contentResolver = mContext.getContentResolver(); Cursor cursor = contentResolver.query( MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, // content://로 시작하는 content table uri projection, // 어떤 column을 출력할 것인지 null, // 어떤 row를 출력할 것인지 null, MediaStore.Audio.Media.TITLE + " ASC"); // 어떻게 정렬할 것인지 if(cursor != null) { while (cursor.moveToNext()) { try{ // MediaStore.Audio.Media.IS_MUSIC 값이 1이면 mp3 음원 파일입니다. // 그리고 밑에는 mp3 metadata 이미지 파일의 uri값을 얻어낸것입니다. // 이렇게 얻어낸 데이터를 arraylist에 저장합니다. if(cursor.getInt(0) != 0) { Uri sArtworkUri = Uri.parse("content://media/external/audio/albumart"); Uri uri = ContentUris.withAppendedId(sArtworkUri, Integer.valueOf(cursor.getString(1))); MusicData data = new MusicData(); data.setMusicImg(uri); data.setMusicTitle(cursor.getString(2)); data.setSinger(cursor.getString(3)); data.setAlbumId(cursor.getString(1)); data.setMusicId(cursor.getString(4)); list.add(data); runOnUiThread(new Runnable() { @Override public void run() { adapter.setAdapterList(list); } }); } }catch (Exception e){ e.printStackTrace(); } } } cursor.close(); } @Override public void onItemClick(AdapterView<?> adapterView, View view, int position, long l) { } private void ListenMusic(int position){ Intent intent = new Intent(this, MusicService.class); intent.putParcelableArrayListExtra("list", list); intent.putExtra("position", position); startService(intent); } }
3. 그리고 서비스 소스
public class MusicService extends Service{ private final String TAG = "MusicService"; private ArrayList<MusicData> list; private MediaPlayer mediaPlayer; private RemoteViews contentView; private NotificationManager mNoti; private Notification noti; private IntentFilter filter; private int nowPosotion; public static String MUSIC_SERVICE_FILTER = "MUSIC_SERVICE_FILTER"; String MUSIC_PREV = "MUSIC_PREV"; String MUSIC_NOW = "MUSIC_NOW"; String MUSIC_NEXT = "MUSIC_NEXT"; String MUSIC_CLOSE = "MUSIC_CLOSE"; @Override public void onDestroy() { super.onDestroy(); Log.e(TAG, "MusicService onDestroy"); unregisterReceiver(btnReceiver); mediaPlayer.release(); mediaPlayer = null; stopForeground(true); } @Override public void onCreate() { super.onCreate(); mediaPlayer = new MediaPlayer(); list = new ArrayList<>(); filter = new IntentFilter(); filter.addAction(MUSIC_PREV); filter.addAction(MUSIC_NOW); filter.addAction(MUSIC_NEXT); filter.addAction(MUSIC_CLOSE); registerReceiver(btnReceiver, filter); AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE); am.requestAudioFocus(focusChangeListener, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN); mediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() { @Override public boolean onError(MediaPlayer mediaPlayer, int i, int i1) { Log.e(TAG, "mediaPlayer error i : " + i + " , i1 : " + i1); return false; } }); } private void MusicOn(int position) { mediaPlayer.reset(); Uri musicURI = Uri.withAppendedPath( MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, "" + list.get(position).getMusicId()); mediaPlayer = MediaPlayer.create(this, musicURI); mediaPlayer.start(); mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mediaPlayer) { Log.e(TAG, "onCompletion"); if(list.size() == nowPosotion + 1){ nowPosotion = 0; } else{ nowPosotion += 1; } ChangeNotiInfomation(); MusicOn(nowPosotion); } }); } private void ChangeNotiInfomation() { contentView.setTextViewText(R.id.txt_title_pend, list.get(nowPosotion).getMusicTitle()); contentView.setTextViewText(R.id.txt_singer_pend, list.get(nowPosotion).getSinger()); contentView.setImageViewUri(R.id.img_pend, list.get(nowPosotion).getMusicImg()); noti.bigContentView = contentView; startForeground(2127, noti); } @Nullable @Override public IBinder onBind(Intent intent) { Log.e(TAG, "onBind"); return null; } @Override public int onStartCommand(Intent intent, int flags, int startId) { nowPosotion = intent.getExtras().getInt("position"); Log.e(TAG, "message : " + nowPosotion); list = intent.getParcelableArrayListExtra("list"); Log.e(TAG, "message : " + list.get(nowPosotion).getMusicTitle()); Intent tent = new Intent(MUSIC_SERVICE_FILTER); PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, tent, PendingIntent.FLAG_UPDATE_CURRENT); contentView = new RemoteViews(getPackageName(), R.layout.layout_notification); Intent prevIntent = new Intent(MUSIC_PREV); Intent nowIntent = new Intent(MUSIC_NOW); Intent nextIntent = new Intent(MUSIC_NEXT); Intent closeIntent = new Intent(MUSIC_CLOSE); PendingIntent pdIntentPrev = PendingIntent.getBroadcast(this, 0, prevIntent, 0); PendingIntent pdIntentNow = PendingIntent.getBroadcast(this, 0, nowIntent, 0); PendingIntent pdIntentNext = PendingIntent.getBroadcast(this, 0, nextIntent, 0); PendingIntent pdIntentClose = PendingIntent.getBroadcast(this, 0, closeIntent, 0); contentView.setTextViewText(R.id.txt_title_pend, list.get(nowPosotion).getMusicTitle()); contentView.setTextViewText(R.id.txt_singer_pend, list.get(nowPosotion).getSinger()); contentView.setImageViewUri(R.id.img_pend, list.get(nowPosotion).getMusicImg()); contentView.setOnClickPendingIntent(R.id.music_prev, pdIntentPrev); contentView.setOnClickPendingIntent(R.id.music_now, pdIntentNow); contentView.setOnClickPendingIntent(R.id.music_next, pdIntentNext); contentView.setOnClickPendingIntent(R.id.music_close, pdIntentClose); Notification.Builder mBuilder = new Notification.Builder(this); mBuilder.setSmallIcon(R.mipmap.ic_launcher); mBuilder.setWhen(System.currentTimeMillis()); mBuilder.setContentIntent(pendingIntent); mBuilder.setContent(contentView); noti = mBuilder.build(); noti.flags = Notification.FLAG_NO_CLEAR; final Notification.BigPictureStyle big = new Notification.BigPictureStyle(); MusicOn(nowPosotion); // mNoti.notify(2127, noti); startForeground(2127, noti); return START_NOT_STICKY; } BroadcastReceiver btnReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (action.equals(MUSIC_PREV)) { Log.e(TAG, "MUSIC_PREV"); if (nowPosotion > 0) { nowPosotion -= 1; ChangeNotiInfomation(); MusicOn(nowPosotion); } else { //다시 시작으로 ChangeNotiInfomation(); MusicOn(nowPosotion); } } if (action.equals(MUSIC_NOW)) { Log.e(TAG, "MUSIC_NOW"); } if (action.equals(MUSIC_NEXT)) { Log.e(TAG, "MUSIC_NEXT"); nowPosotion += 1; ChangeNotiInfomation(); MusicOn(nowPosotion); } if (action.equals(MUSIC_CLOSE)) { Log.e(TAG, "MUSIC_CLOSE"); // NotificationManager notificationManager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE); // notificationManager.cancel(2127); stopForeground(true); mediaPlayer.reset(); Intent closeIntent = new Intent(MUSIC_SERVICE_FILTER); sendBroadcast(closeIntent); } } }; private AudioManager.OnAudioFocusChangeListener focusChangeListener = new AudioManager.OnAudioFocusChangeListener() { public void onAudioFocusChange(int focusChange) { AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE); switch (focusChange) { case (AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK): Log.e(TAG, "OnAudioFocusChangeListener AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK"); break; case (AudioManager.AUDIOFOCUS_LOSS_TRANSIENT): Log.e(TAG, "OnAudioFocusChangeListener AUDIOFOCUS_LOSS_TRANSIENT"); break; case (AudioManager.AUDIOFOCUS_LOSS): Log.e(TAG, "OnAudioFocusChangeListener AUDIOFOCUS_LOSS"); mediaPlayer.stop(); contentView.setImageViewResource(R.id.music_now, R.drawable.play_pause); noti.bigContentView = contentView; startForeground(2127, noti); break; case (AudioManager.AUDIOFOCUS_GAIN): Log.e(TAG, "OnAudioFocusChangeListener AUDIOFOCUS_GAIN"); break; default: break; } } }; // @Override // public void onCompletion(MediaPlayer mediaPlayer) { // // Log.e(TAG, "onCompletion"); // // if(list.size() == nowPosotion + 1){ // nowPosotion = 0; // } else{ // nowPosotion += 1; // } // // ChangeNotiInfomation(); // MusicOn(nowPosotion); // } @Override public void onTaskRemoved(Intent rootIntent) { super.onTaskRemoved(rootIntent); Log.e(TAG, "onTaskRemoved"); } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); Log.e(TAG, "onConfigurationChanged"); } @Override public boolean onUnbind(Intent intent) { Log.e(TAG, "onUnbind"); return super.onUnbind(intent); } }
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="100dp" android:layout_centerVertical="true"> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" android:layout_centerVertical="true" android:layout_marginLeft="20dp"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:textSize="11sp" android:text="TestApp" android:textColor="#1266FF"/> <TextView android:id="@+id/txt_title_pend" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="3dp" android:textSize="15sp" android:text="test" android:textStyle="bold" /> <TextView android:id="@+id/txt_singer_pend" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="3dp" android:textSize="12sp" android:text="test" /> </LinearLayout> <ImageView android:id="@+id/img_pend" android:layout_width="45dp" android:layout_height="45dp" android:layout_marginRight="20dp" android:layout_centerVertical="true" android:layout_alignParentRight="true"/> <LinearLayout android:layout_width="wrap_content" android:layout_height="35dp" android:orientation="horizontal" android:layout_toLeftOf="@id/img_pend" android:layout_marginRight="15dp" android:layout_centerVertical="true" android:gravity="center_vertical"> <ImageButton android:id="@+id/music_prev" android:layout_width="16dp" android:layout_height="16dp" android:layout_marginRight="10dp" android:background="@drawable/play_prev" /> <ImageButton android:id="@+id/music_now" android:layout_width="16dp" android:layout_height="16dp" android:layout_marginRight="10dp" android:background="@drawable/play_pause" /> <ImageButton android:id="@+id/music_next" android:layout_width="16dp" android:layout_height="16dp" android:layout_marginRight="10dp" android:background="@drawable/play_next" /> <ImageButton android:id="@+id/music_close" android:layout_width="16dp" android:layout_height="16dp" android:background="@drawable/play_close" /> </LinearLayout> </RelativeLayout>
안드로이드 Manifest에서 receiver와 service 등록 잊지마세요.
<receiver android:name=".Screen.ScreenReceiver" /> <service android:name=".music.MusicService" android:enabled="true"> <intent-filter> <action android:name="MUSIC_SERVICE_FILTER"/> </intent-filter> </service>
'프로그램 > Android' 카테고리의 다른 글
전화번호부에서 전화번호 긁어오기 (0) | 2017.08.28 |
---|---|
안드로이드 Notification 이미지와 큰사이즈 (0) | 2017.08.28 |
안드로이드 mp3플레어어 만들기(2. Cursor를 이용하여 mp3 데이터 가져오기) (0) | 2017.08.07 |
안드로이드 mp3플레어어 만들기(1. 커스텀 Listview 생성) (0) | 2017.08.04 |
안드로이드 BarCode Reader (0) | 2016.09.27 |