【达内课程】音乐播放器4.0(播放)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010356768/article/details/83182691

效果图
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
创建PlayMusicService

import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.Binder;
import android.os.IBinder;
import android.support.annotation.Nullable;

import java.io.IOException;

/**
 * 播放音乐服务
 */
public class PlayMusicService extends Service {
    //Service是单例的,只创建1次,因此在这里创建MediaPlayer,保证只有一个
    private MediaPlayer mediaPlayer = new MediaPlayer();


    /**
     * 当service实例创建时执行
     */
    @Override
    public void onCreate() {
        super.onCreate();
        //给mediaPlayer加监听
        mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
            //音乐已经准备好
            @Override
            public void onPrepared(MediaPlayer mediaPlayer) {
                mediaPlayer.start();
            }
        });
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return new MusicBinder();
    }

    public class MusicBinder extends Binder{
        //定义供客户端调用的方法
        public void playMusic(String url){
            try {
                mediaPlayer.reset();
                mediaPlayer.setDataSource(url);
                mediaPlayer.prepareAsync();//异步准备
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
    }
}

AndroidManifest.xml
对service进行注册

        <service android:name=".service.PlayMusicService"/>

MainActivity中绑定Service

public class MainActivity extends FragmentActivity {
    ......
    private ServiceConnection conn;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        setViews();
        //设置ViewPager适配器
        setViewPagerAdapter();
        //设置监听
        setListeners();
        //绑定Service
        bindMusicService();
    }

    /**
     * 绑定Service
     */
    private void bindMusicService() {
        Intent intent = new Intent(this, PlayMusicService.class);
        conn = new ServiceConnection(){

            @Override
            public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
                PlayMusicService.MusicBinder binder = (PlayMusicService.MusicBinder)iBinder;
                //把binder对象交给Fragment
                NewMusicListFragment f1 = (NewMusicListFragment)fragments.get(0);
                f1.setMusicBinder(binder);
            }
            //绑定成功执行该方法
            @Override
            public void onServiceDisconnected(ComponentName componentName) {

            }
        };
        this.bindService(intent,conn, Service.BIND_AUTO_CREATE);
    }

    @Override
    protected void onDestroy() {
        this.unbindService(conn);
        super.onDestroy();
    }
	......
}

NewMusicListFragment中调用service中播放音乐方法

/**
 * 新歌榜列表
 */
public class NewMusicListFragment extends Fragment {
    ......
    private PlayMusicService.MusicBinder binder;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
    private void setListeners() {
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
                final Music music = musics.get(i);
                String songId = music.getSong_id();
                Toast.makeText(getActivity(),"position:"+i,Toast.LENGTH_SHORT).show();
                //执行业务层 加载这首歌曲的基本信息
                model.loadMusicInfoBySongId(songId, new MusicInfoCallback() {
                    @Override
                    public void onMusicInfoLoaded(Songinfo songinfo, BitrateModel bitrateModel) {
                        music.setSonginfo(songinfo);
                        music.setBitrate(bitrateModel);
                        //准备通过url地址执行播放业务
                        String fileLink = bitrateModel.getFile_link();
                        //播放音乐
                        binder.playMusic(fileLink);
                    }
                });
            }
        });
    }
   ......
}

上面实现了播放的功能,下面实现播放音乐时底部显示对应歌曲信息的功能
在这里插入图片描述

界面显示
activity_main增加以下布局

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:layout_alignParentBottom="true"
        android:gravity="center_vertical"
        android:paddingLeft="10dp"
        android:paddingRight="10dp"
        android:background="@color/colorPrimary"
        >

        <com.example.xx.v4.ui.CircleImageView
            android:id="@+id/img_music_thumb"
            android:layout_width="40dp"
            android:layout_height="40dp"
            android:src="@mipmap/ic_launcher"
            android:layout_marginRight="10dp"/>


        <TextView
            android:id="@+id/tv_music_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="歌名"
            android:textColor="@android:color/white"/>

    </LinearLayout>

其中圆形头像用的CircleImageView,可以直接把Github项目中的CircleImageView.java和res下的attrs复制到项目中用即可
https://github.com/hdodenhof/CircleImageView

在点击播放歌曲后,底部显示对应歌曲信息,需要知道当前播放的歌曲是哪一首,我们可以存歌曲列表和点击的position来确定歌曲,可以用Application实现

创建MusicApplication

public class MusicApplication extends Application {
    private List<Music> musicList;
    private int position;
    public static MusicApplication app;

    @Override
    public void onCreate() {
        super.onCreate();
        app = this;
    }

    public static MusicApplication getApp(){
        return app;
    }

    public List<Music> getMusicList() {
        return musicList;
    }

    public void setMusicList(List<Music> musicList) {
        this.musicList = musicList;
    }

    public int getPosition() {
        return position;
    }

    public void setPosition(int position) {
        this.position = position;
    }

    /**
     * 获取当前正在播放的音乐
     * @return
     */
    public Music getCurrentMusic(){
        return musicList.get(position);
    }
}

AndroidManifest中注册

<application
        android:name=".MusicApplication"
        ......
        android:theme="@android:style/Theme.Light.NoTitleBar">
        <service android:name=".service.PlayMusicService"/>
        ......
    </application>

NewMusicListFragment中,在点击listview时,在application中存入音乐播放列表和position

private void setListeners() {
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, final int i, long l) {
                final Music music = musics.get(i);
                String songId = music.getSong_id();
                Toast.makeText(getActivity(),"position:"+i,Toast.LENGTH_SHORT).show();
                //执行业务层 加载这首歌曲的基本信息
                model.loadMusicInfoBySongId(songId, new MusicInfoCallback() {
                    @Override
                    public void onMusicInfoLoaded(Songinfo songinfo, BitrateModel bitrateModel) {
                        music.setSonginfo(songinfo);
                        music.setBitrate(bitrateModel);
                        //把当前播放列表和position都存入application
                        MusicApplication app = MusicApplication.getApp();
                        app.setMusicList(musics);
                        app.setPosition(i);
                        //准备通过url地址执行播放业务
                        String fileLink = bitrateModel.getFile_link();
                        //播放音乐
                        binder.playMusic(fileLink);
                    }
                });
            }
        });
    }

当音乐播放开始时,service通知activity播放开始
因此我们需要发送广播
PlayMusicService中

/**
     * 当service实例创建时执行
     */
    @Override
    public void onCreate() {
        super.onCreate();
        //给mediaPlayer加监听
        mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
            //音乐已经准备好
            @Override
            public void onPrepared(MediaPlayer mediaPlayer) {
                mediaPlayer.start();
                //发送广播,通知activity音乐已经开始播放
                Intent intent = new Intent (Globalconsts.ACTION_MUSIC_STARTED);
                sendBroadcast(intent);
            }
        });
    }

创建常量类GlobalConsts

/**
 * 常量类
 */
public class Globalconsts {
    //音乐开始播放 广播action
    public static final String ACTION_MUSIC_STARTED = "ACTION_MUSIC_STARTED";

}

BitmapUtils中增加根据图片路径加载bitmap的方法

public static void loadBitmap(final String path, final BitmapCallback bitmapCallback){
        AsyncTask<String,String,Bitmap> task = new AsyncTask<String, String, Bitmap>() {
            @Override
            protected Bitmap doInBackground(String... strings) {
                try {
                    //先从内存缓存中读
                    //再从文件中读
                    String filename = path.substring(path.lastIndexOf("/")+1);
                    File file = new File(MusicApplication.getApp().getCacheDir(),"images/"+filename);
                    Bitmap b = bitmap(file);
                    if(b!=null){
                        return b;
                    }
                    InputStream is = HttpUtils.getInputStream(path);
                    b = BitmapFactory.decodeStream(is);
                    //下载下来的图片,存入缓存中
                    save(b,file);
                    return b;
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return null;
            }

            //主线程中执行回调方法
            @Override
            protected void onPostExecute(Bitmap bitmap) {
                bitmapCallback.onBitmapLoaded(bitmap);
            }
        };
        task.execute();
    }

增加接口BitmapCallback

public interface BitmapCallback {
    /**
     * 当图片下载成功之后的回调方法
     * @param bitmap
     */
    void onBitmapLoaded(Bitmap bitmap);
}

注册接收器
MainActivity

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        setViews();
        //设置ViewPager适配器
        setViewPagerAdapter();
        //设置监听
        setListeners();
        //绑定Service
        bindMusicService();
        //注册广播接收器
        registMusicReceiver();
    }

    /**
     * 注册广播接收器
     */
    private void registMusicReceiver() {
        receiver = new MusicInfoBroadCastReceiver();
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(Globalconsts.ACTION_MUSIC_STARTED);
        this.registerReceiver(receiver,intentFilter);
    }

    /**
     * 接收音乐信息的广播接收器
     */
    class MusicInfoBroadCastReceiver extends BroadcastReceiver{

        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if(action.equals(Globalconsts.ACTION_MUSIC_STARTED)){
                //开始播放音乐,获取当前音乐对象
                MusicApplication app = MusicApplication.getApp();
                Music music = app.getCurrentMusic();
                String pic = music.getPic_small();
                final String title = music.getTitle();
                BitmapUtils.loadBitmap(pic, new BitmapCallback() {
                    @Override
                    public void onBitmapLoaded(Bitmap bitmap) {
                        if(bitmap != null){
                           imgMusicThumb.setImageBitmap(bitmap);
                        }
                    }
                });
               tvMusicTitle.setText(title);
            }
        }
    }

    @Override
    protected void onDestroy() {
        this.unbindService(conn);
        this.unregisterReceiver(receiver);
        super.onDestroy();
    }

现在让图片转起来
MusicInfoBroadCastReceiver中在设置完图片后,设置动画

BitmapUtils.loadBitmap(pic, new BitmapCallback() {
                    @Override
                    public void onBitmapLoaded(Bitmap bitmap) {
                        if(bitmap != null){
                           imgMusicThumb.setImageBitmap(bitmap);
                           //执行旋转动画
                            RotateAnimation animation = new RotateAnimation(0,360,imgMusicThumb.getWidth()/2,imgMusicThumb.getWidth()/2);
                            animation.setDuration(10000);
                            animation.setRepeatCount(Animation.INFINITE);
                            animation.setInterpolator(new LinearInterpolator());//匀速旋转
                            imgMusicThumb.startAnimation(animation);
                        }
                        tvMusicTitle.setText(title);
                    }
                });

猜你喜欢

转载自blog.csdn.net/u010356768/article/details/83182691