安卓Service实现通知栏⾳乐播放器,切换歌曲,类似QQ⾳乐
引⾔:
这样的⼀个⾳乐播放器,⽤到了安卓四⼤组件的其中三个,等于说是⼀个⽐较综合性的⼩功能。实现⽅法其实有很多,我这⾥给出⾃⼰的⽅法,不喜勿喷。
需求分析
1.⾳乐播放器,那我们需要⼀个帮助类,来构建单例⾳乐播放器对象
ities;
t.Context;
t.res.AssetFileDescriptor;
dia.AudioManager;
dia.MediaPlayer;
import android.Uri;
import java.io.IOException;
public class MediaHelper {
private static MediaHelper instance;
private Context mContext;
private MediaPlayer mMediaPlayer;
private OnMediaHelperListener mOnMediaHelperListener;
private int mResID=-5;
public void setmOnMediaHelperListener(OnMediaHelperListener mOnMediaHelperListener){
this.mOnMediaHelperListener = mOnMediaHelperListener;
杨宗纬 原}
public static MediaHelper getInstance(Context context){
if(instance==null){
synchronized(MediaHelper.class){
if(instance==null){
instance=new MediaHelper(context);
}
}
}
return instance;
}
private MediaHelper(Context context){
mContext=context;
mMediaPlayer=new MediaPlayer();
}
/**
* 当播放本地uri中⾳时调⽤
* @param path
*/
public void setPath(String path){
if(mMediaPlayer.isPlaying()){
}
try{
mMediaPlayer.setDataSource(mContext, Uri.parse(path));
}catch(IOException e){
e.printStackTrace();
}
mMediaPlayer.prepareAsync();
mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener(){
@Override
public void onPrepared(MediaPlayer mp){
if(mOnMediaHelperListener !=null){
}
}
});
mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener(){ @Override
public void onCompletion(MediaPlayer mp){
if(mOnMediaHelperListener !=null){
}
}
});
杨伶俐 程兰}
/**
* 当调⽤raw下的⽂件时使⽤
* @param resid
*/
public void setRawFile(int resid){
if(resid==mResID&&mResID!=-5){
//相同⾳乐id或者且不是第⼀次播放,就直接返回
return;
}
//mOnInitMusicListener.initMode();
mResID=resid;
final AssetFileDescriptor afd = Resources().openRawResourceFd(resid);
try{
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer.FileDescriptor(), StartOffset(), Length());            mMediaPlayer.prepareAsync();
}catch(IOException e){
e.printStackTrace();
}
mMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener(){ @Override
public void onPrepared(MediaPlayer mp){
if(mOnMediaHelperListener !=null){
try{
afd.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
});
mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener(){ @Override
public void onCompletion(MediaPlayer mp){
if(mOnMediaHelperListener !=null){
}
}
});
}
public void start(){
if(mMediaPlayer.isPlaying()){
return;
}
mMediaPlayer.start();
if(mOnMediaHelperListener!=null){
}
}
}
public void pause(){
if(!mMediaPlayer.isPlaying()){
return;
}
mMediaPlayer.pause();
if(mOnMediaHelperListener!=null){
}
}
public boolean isPlaying(){
if(mMediaPlayer!=null&&mMediaPlayer.isPlaying()){
return true;
}
return false;
}
public int getCurrentPosition(){
四川话歌曲CurrentPosition();
}
public int getDuration(){
Duration();
}
public void seekTo(int progress){
mMediaPlayer.seekTo(progress);
}
public interface OnMediaHelperListener {
//⾳乐准备好之后调⽤
郑爽处给了张翰吗void onPrepared(MediaPlayer mp);
//⾳乐暂停状态
void onPauseState();
/
/⾳乐播放状态
void onPlayingState();
}
}
2.⾸先,要实现播放器显⽰在通知栏⾥⾯,毫⽆疑问,要创建通知,以前台服务的形式显⽰<1>创建通知:
ities;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
t.Context;
t.Intent;
import android.widget.RemoteViews;
张杰照片app.NotificationCompat;
ample.jackandrose.R;
ample.jackandrose.activities.Main2Activity;
ample.jackandrose.activities.MainActivity;
public class NotifyHelper {
private static NotifyHelper instance;
private Context mContext;
public static NotifyHelper getInstance(Context context){
if(instance==null){
instance=new NotifyHelper(context);
}
return instance;
}
private NotifyHelper(Context context){
mContext=context;
}
public void CreateChannel(String channel_id,CharSequence channel_name,String description){
//8.0以上版本通知适配
if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O){
NotificationChannel notificationChannel=new NotificationChannel(channel_id,channel_name, NotificationManager.IMPORTANCE_HIGH);            notificationChannel.setDescription(description);
NotificationManager SystemService(NotificationManager.class);
}
}
/**
* 返回⼀个前台通知
* @param channel_id  通知渠道id,注意8.0创建通知的时候渠道id与此要匹配
* @param musicPicture 数据对象
* @param remoteViews ⾃定义通知样式的对象,但是与View不同,不提供findViewById⽅法,详细建议看看源码和官⽅⽂档
* @return
*/
public Notification createForeNotification(String channel_id, MusicPicture musicPicture,RemoteViews remoteViews){
Intent intent=new Intent(mContext, MainActivity.class);
PendingIntent Activity(mContext,0,intent,0);
NotificationCompat.Builder builder=new NotificationCompat.Builder(mContext,channel_id)
.setSmallIcon(R.mipmap.qqyinyue)
.setStyle(new NotificationCompat.DecoratedCustomViewStyle())
.setCustomBigContentView(remoteViews)
.setContentIntent(mainIntent)
.setPriority(NotificationCompat.PRIORITY_DEFAULT);
return builder.build();
}
}
细⼼的朋友肯定发现了,我构建通知的时候picture对象没有使⽤到,我也不想改了,就放着吧~
需要注意的是,RemoteViews不⽀持部分布局和控件,ConstraintLayout,⽤于显⽰⾳乐进度的SeekBar,还有各种第三⽅库,⽐如CircleImageView,这些都不被⽀持,反正我刚开始写出来的布局,通知界⾯便没有正确显⽰。
<2>布局代码:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android="schemas.android/apk/res/android"
app="schemas.android/apk/res-auto"
id="@+id/cl_music_player"
layout_width="match_parent"
layout_height="wrap_content"
background="@color/myActionBarColor"
orientation="horizontal">
<ImageView
id="@+id/iv_music_icon"
layout_width="@dimen/myBigMusicIconSize"
layout_height="@dimen/myBigMusicIconSize"
layout_gravity="center"
scaleType="fitXY"
layout_marginLeft="16dp"
src="@mipmap/qqyinyue"/>周杰伦 好久不见
<LinearLayout
orientation="vertical"
layout_weight="1"
layout_width="0dp"
layout_height="wrap_content">
<FrameLayout
layout_width="match_parent"
layout_height="wrap_content"
layout_weight="1"
>
<ImageView
id="@+id/iv_music_last_song"
layout_width="@dimen/myMusicIconSize"
layout_height="@dimen/myMusicIconSize"
layout_margin="16dp"
layout_gravity="left|center_vertical"
src="@mipmap/music_last"/>
<ImageView
id="@+id/iv_music_play"
layout_width="@dimen/myIconSize"
layout_height="@dimen/myIconSize"
layout_margin="16dp"
src="@mipmap/play_music"
layout_gravity="center"/>
<ImageView
id="@+id/iv_music_next_song"
layout_width="@dimen/myMusicIconSize"
layout_height="@dimen/myMusicIconSize"
layout_margin="16dp"
src="@mipmap/music_next"
layout_gravity="right|center_vertical"/>
</FrameLayout>
</LinearLayout>
</LinearLayout>
<3>创建主服务,⽤于显⽰播放器和控制整个⾳乐播放的服务,并且这⾥⾯实现了⾳乐播放帮助类的外放接⼝:
ample.jackandrose.services;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.Service;
t.Intent;
t.IntentFilter;
dia.MediaPlayer;
import android.os.Binder;