用户注册



邮箱:

密码:

用户登录


邮箱:

密码:
记住登录一个月忘记密码?

发表随想


还能输入:200字

云代码会员    -  云代码空间

——

《简约音乐播放器》

2018-06-14|454阅||

摘要:1. 项目名称:MyMusic,项目结构详图,如图1.1所示:   图1.1 2. 项目实现效果图,如下8图所示:             图2.1 主界面                       图2.2 音乐列表元 图2.1和图2.2是

1. 项目名称:MyMusic,项目结构详图,如图1.1所示:

 

1.1

2. 项目实现效果图,如下8图所示:

 

          2.1 主界面                       图2.2 音乐列表元

2.1和图2.2是布局效果,实现文件分别是activity_main.xmllist_item.xml

 

          2.3 获取本地音乐信息                   图2.4 歌词滚动界面

2.3和图2.4为项目链接真机调试时初始界面,其中音乐列表和歌词滚动界的切换由控制,控件分别控制退、播放/暂停、进功能。

 

        2.5 播放本地音乐                     图2.6 歌词滚动界面

 

       2.7 播放本地音乐                         图2.8 歌词滚动界面

2.5~2.8为本地音乐播放时界面,通过点击选择要播放音乐进行播放,音乐选中效果为,当音乐被选中时,播放按钮立即切换为暂停按钮,同时顶部会显示正在播放音乐的名称和其艺术家名,点击暂停按钮或再次点击选中的音乐,当前音乐就会暂停播放,这是按钮恢复为播放按钮。

 

3. AndroidManifest.xml配置文件:(注意:申请SD卡权限和注册服务

Ø 申请SD卡读写权限:

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Ø 注册MainActivity,并注为主Activity

    <activity android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

Ø 注册服务器MusicService

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

Ø 其他配置。

    

4. activity_main.xml音乐界面布局设计,采用了LinearLayout线性布局,使用控件有TextViewListViewScrollViewSeekBarImageButton,界面分为三板块,分别为正在播放的音乐名称和其艺术家、音乐列表/歌词滚动加界面、播放等控件。

 

5. list_item.xml音乐列表元,采用了RelativeLayout相对布局和LinearLayout线性布局组合的方式布局,同时使用了两个ImageButton控件和四个TextView控件,实现分为专辑图(这里为默认白音符,点歌播放时隐藏)、暂停图标(点歌播放时显示)、歌曲名称、其艺术家、歌曲时长、歌曲大小。

 

6. MainActivity主类:(注意事项:该项目是在真机下调试的,调试时,注意在手机的“权限管理”处找到项目软件“MyMusic”,点击打开设置打开“存储”权限,否则无法读取本地音乐

类名

MainActivity

类功能描述

主体类,继承了Activity

类属性

   rivate MusicService musicService; //声明 MusicService 对象
    private Intent intent; //发送广播
    private boolean isBind; //服务绑定标识
    private boolean isShowOrNot = false; //音乐列表按钮标识
    private boolean isSeekBarChanging = false; //拖动进度时与Thread更新播放进度条冲突标识
    //测试list
    private ListView list_view; //音乐列表
    private List<MusicInfo>musicList;
    private boolean isPlaying; //播放标识
    int currentPositon = 0; //当前进度,用于快进、快退
    private int music_position = -1; //当前音乐位置
    private ScrollView scroll_view; //歌词滚动
    private LinearLayout surf_view; //歌词界面
    private TextView play_title; //正在播放的音乐
    private TextView play_artist; //作者
    private ImageButton music_list; //列表
    private ImageButton music_previous; //快退
    private ImageButton music_play; //播放
    private ImageButton music_pause; //暂停
    private ImageButton music_stop; //停止
    private ImageButton music_next; //快进
    private TextView play_time; //播放时间
    private TextView all_time; //总时间
    private SeekBar seekbar; //进度条

    //用于播放模式函数
    private final int PREVIOUS_MUSIC = 1;   //上一首
    private final int NEXT_MUSIC = 2;      //下一首
    private final int LOOP_MODE = 3;       //循环播放
    private final int RANDOM_MODE = 4;     //随机播放

类实现的方法

//为了接受IBinder实例,必须创建一个 ServiceConnection 实例,并传给MusicService()

private ServiceConnection serviceConnection = new ServiceConnection() {

//当service被绑定的时候回调该函数
public void onServiceConnected(ComponentName componentName, IBinder iBinder) {}

//服务器断开或关闭的时候调用该方法
public void onServiceDisconnected(ComponentName componentName) {}

}
protected void onCreate(Bundle savedInstanceState) {}

//初始化界面信息
public void initView(){}

//定义一个内部类,声明list_item相应的控件引用
public final class ViewHolder {}

//适配器
private class MyAdapter extends BaseAdapter {

//构造函数

public MyAdapter(Context context, List<MusicInfo> musicList) {}

public int getCount(){}
public Object getItem(int position){}
public long getItemId(int position){}

public View getView(final int position, View convertView, ViewGroup parent){}

}

//进度条事件响应
private class SeekBarListener implements SeekBar.OnSeekBarChangeListener{}

//list点击音乐列表元事件响应
private void itemClick(ViewHolder holder, int position) {}

//按钮事件响应
public void onClick(View view) {}

//解除绑定
protected void onDestroy() {}

//音乐播放指引
Handler handler = new Handler();
Runnable updateThread = new Runnable() { //使用线程循环更新当前播放进度,即更新进度条
public void run() {}

}

//播放模式
private void MusicInterface(int mode,int msg,List<MusicInfo> musicList){}

 

7. MusicService音乐服务:

类名

MusicService

类功能描述

音乐服务类,继承了Service(包含了暂停、播放、停止、缓冲、重置等等)

类属性

public MediaPlayer player; //声明 MediaPlayer 对象
private MediaController controller; //声明 MediaController 对象

类实现的方法

//onBind方法

public IBinder onBind(Intent arg0) {}

public void onCreate() {}

public int onStartCommand(Intent intent, int flags, int startId) {}

//开始播放
public void musicPlay(String path) {}

//缓冲完成后执行
private final class PreparedListener implements MediaPlayer.OnPreparedListener {}

//播放
public void start(){}
//暂停
public void pause(){}

//停止
public void stop(){}

//缓冲
public void prepare(){}

//重置
public void reset(){}

//是否播放
public boolean isPlaying(){}

//解绑服务
public void onDestroy() {}

//当前音乐的总时长
public int getDuration() {}
//当前播放的位置
public int getCurrentPosition() {}
//读取资源
public void setDataSource(String path){}

//MediaController
class MediaController extends Binder {

//返回MusicService实例
public MusicService getService(){return MusicService.this;}

}

 

8. MusicInfo歌曲信息实体类:

类名

MusicInfo

类功能描述

歌曲信息实体类

类属性

    private long id; // 歌曲ID 3
    private String title; // 歌曲名称 0
    private String album; // 专辑 7
    private int albumId;// 专辑ID 6
    private String displayName; // 显示名称 4
    private String artist; // 歌手名称 2
    private int duration; // 歌曲时长 1
    private int size; // 歌曲大小 8
    private String url; // 歌曲路径 5
    private String lrcTitle; // 歌词名称
    private String lrcSize; // 歌词大小

类实现的方法

GetterSetter方法

 

9. MusicUtils音乐工具类:

类名

MusicUtils

类功能描述

音乐工具类(包含了媒体库读取歌词信息、时间处理、文件大小处理)

类属性

//生成动态数组,并转载数据
List<MusicInfo> musicList = new ArrayList<MusicInfo>();

类实现的方法

//读取方法:读取SD卡里的歌曲信息,保存在List当中,以供Adapter调用显示
    public static List<MusicInfo> getMusicData(Context context){}

// 时间转化处理,将时间修改为常用的格式
public static String formatTime(int time){}

// 文件大小转换处理,将B转换为MB
public static String toMB(int size) {}

 

10. 资源文件:

 

11. 其他:

 

12. 附录:

AndroidManifest.xml配置文件:(注意:申请SD卡权限和注册服务

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.admin.musicapp">
    <!-- 允许访问SD卡 -->
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <application
        android:allowBackup="true"
        android:icon="@mipmap/mymusic"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <!--注册服务-->
        <service android:name=".MusicService"/>
    </application>
</manifest>

activity_main.xml音乐界面布局设计:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="@drawable/deeppink"
    tools:context=".MainActivity">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        android:layout_marginTop="10.0dip">
        <TextView
            android:id="@+id/music_title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:textSize="18.0dip"
            android:textStyle="bold"
            android:gravity="center"
            android:text="正在播放歌曲名称"/>
        <!--android:text="@String/music"/>-->
        <TextView
            android:id="@+id/music_author"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="未知艺术家"
            android:gravity="center"/>
    </LinearLayout>
    <ListView
        android:id="@+id/list_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1">
    </ListView>
    <LinearLayout
        android:id="@+id/surf_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="horizontal"
        android:layout_weight="1"
        android:visibility="gone">
        <ScrollView
            android:id="@+id/scroll_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="horizontal">
            <TextView
                android:id="@+id/music_lyric"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:text="好歌不容错过"
                android:textColor="#fff"
                android:layout_weight="1"
                android:textAppearance="?android:attr/textAppearanceLarge"/>
        </ScrollView>
    </LinearLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_marginTop="10.0dip"
        android:orientation="horizontal">
        <TextView
            android:id="@+id/play_time"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="5.0dip"
            android:text="00:00"
            android:textSize="15.0dip" />
        <SeekBar
            android:id="@+id/seekbar"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginLeft="2.0dip"
            android:layout_marginRight="2.0dip"
            android:layout_weight="1" />
        <TextView
            android:id="@+id/all_time"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginRight="5.0dip"
            android:text="00:00"
            android:textSize="15.0dip"/>
    </LinearLayout>
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_marginBottom="10.0dip">
        <ImageButton
            android:id="@+id/music_list"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@mipmap/music" />
        <ImageButton
            android:id="@+id/music_previous"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="50.0dip"
            android:background="@mipmap/previous"/>
        <ImageButton
            android:id="@+id/music_pause"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10.0dip"
            android:background="@mipmap/pause"
            android:visibility="gone"/>
        <ImageButton
            android:id="@+id/music_play"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10.0dip"
            android:background="@mipmap/play"/>
        <ImageButton
            android:id="@+id/music_next"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="10.0dip"
            android:background="@mipmap/next"/>
        <ImageButton
            android:id="@+id/music_search"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="50.0dp"
            android:background="@mipmap/search"/>
    </LinearLayout>
</LinearLayout>

list_item.xml音乐列表元:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/RelativeLayout1"
    android:layout_width="match_parent"
    android:layout_height="55.0dp"
    android:orientation="vertical"
    android:padding="10dp">
    <LinearLayout
        android:id="@+id/albumLayout"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
    <ImageButton
        android:id="@+id/albumImage"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@mipmap/ic_launcher_white" />
    <ImageButton
        android:id="@+id/play_pause"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@mipmap/pause_alt"
        android:visibility="gone"/>
    </LinearLayout>
    <TextView
        android:id="@+id/music_duration"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:layout_gravity="center"
        android:layout_marginRight="5.0dp"
        android:text="@string/time"
        android:textColor="@android:color/white" />
    <TextView
        android:id="@+id/music_size"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_below="@id/music_duration"
        android:layout_gravity="center"
        android:layout_marginRight="3.0dp"
        android:text="@string/size"
        android:textColor="@android:color/white" />
    <TextView
        android:id="@+id/music_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_marginLeft="5dp"
        android:layout_toRightOf="@+id/albumLayout"
        android:text="@string/siger"
        android:textColor="@android:color/white" />
    <TextView
        android:id="@+id/music_artist"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignLeft="@+id/music_title"
        android:layout_below="@id/music_title"
        android:text="@string/artist"
        android:textColor="@android:color/white" />
</RelativeLayout>

MainActivity主类:(注意:该项目是在真机下调试的,调试时,注意在手机的“权限管理”处找到项目软件“MyMusic”的存储权限打开

/**
 * Created by Admin on 2018/5/10.
 */

public class MusicActivity extends Activity implements View.OnClickListener {
    private MusicService musicService; //声明 MusicService 对象
    private Intent intent; //发送广播
    private boolean isBind; //服务绑定标识
    private boolean isShowOrNot = false; //音乐列表按钮标识
    private boolean isSeekBarChanging = false; //拖动进度时与Thread更新播放进度条冲突标识

    //测试list
    private ListView list_view; //音乐列表
    private List<MusicInfo>musicList;
    private boolean isPlaying; //播放标识
    int currentPositon = 0; //当前进度,用于快进、快退
    private int music_position = -1; //当前音乐位置

    private ScrollView scroll_view; //歌词滚动
    private LinearLayout surf_view; //歌词界面
    private TextView play_title; //正在播放的音乐
    private TextView play_artist; //作者
    private ImageButton music_list; //列表
    private ImageButton music_previous; //快退
    private ImageButton music_play; //播放
    private ImageButton music_pause; //暂停
    private ImageButton music_stop; //停止
    private ImageButton music_next; //快进
    private TextView play_time; //播放时间
    private TextView all_time; //总时间
    private SeekBar seekbar; //进度条

    //为了接受IBinder实例,必须创建一个 ServiceConnection 实例,并传给MusicService()
    private ServiceConnection serviceConnection = new ServiceConnection() {
        //当service被绑定的时候回调该函数
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            MusicService.MediaController binder = (MusicService.MediaController) iBinder;
            musicService = binder.getService();
            // 设置进度条的最大值
            seekbar.setMax(musicService.getDuration());
            //每次播放都要加载音乐时长
            seekbar.setProgress(musicService.getDuration());
            //更新进度条
            handler.post(updateThread);
            Log.i("tag","服务器已经连接......");
        }
        //服务器断开或关闭的时候调用该方法
        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            musicService = null; //MusicService实例不可再用
            Log.i("tag","服务器已经断开......");
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        // 创建一个用于启动服务的显示意图,指向 MusicService 类
        intent  = new Intent(MusicActivity.this,MusicService.class);
        initView(); //初始化界面信息
        // 绑定服务,同时服务开启,如果成功则返回true,否则返回false
        isBind = bindService(intent, serviceConnection, BIND_AUTO_CREATE);
        if (isBind) {
            Log.i("tag","音乐播放器服务绑定成功!");
        } else {
            Log.i("tag","音乐播放器服务绑定失败!");
        }
    }
    //初始化界面信息
    public void initView(){
        scroll_view= (ScrollView) findViewById(R.id.scroll_view);
        surf_view = (LinearLayout) findViewById(R.id.surf_view);
        list_view = (ListView) findViewById(R.id.list_view);
        play_title=(TextView) this.findViewById(R.id.music_title);
        play_artist=(TextView) this.findViewById(R.id.music_author);
        seekbar = (SeekBar) findViewById(R.id.seekbar);
        play_time= (TextView) findViewById(R.id.play_time);
        all_time= (TextView) findViewById(R.id.all_time);
        music_list = (ImageButton)findViewById(R.id.music_list);
        music_previous = (ImageButton)findViewById(R.id.music_previous);
        music_play = (ImageButton)findViewById(R.id.music_play);
        music_pause = (ImageButton)findViewById(R.id.music_pause);
        music_stop = (ImageButton)findViewById(R.id.music_stop);
        music_next = (ImageButton)findViewById(R.id.music_next);

        //注册监听事件
        seekbar.setOnSeekBarChangeListener(new SeekBarListener());
        music_list.setOnClickListener(this);
        music_previous.setOnClickListener(this);
        music_play.setOnClickListener(this);
        music_pause.setOnClickListener(this);
        music_stop.setOnClickListener(this);
        music_next.setOnClickListener(this);
        //测试list
        musicList = MusicUtils.getMusicData(MusicActivity.this);
        Log.i("tag", "MyAdapter");
        MyAdapter adapter = new MyAdapter(MusicActivity.this,musicList);
        list_view.setAdapter(adapter);
    }
    //定义一个内部类,声明list_item相应的控件引用
    public final class ViewHolder {
        public RelativeLayout listitem; //用于监听
        public ImageButton albumImage; //专辑
        public ImageButton play_pause; //暂停
        public TextView music_title; //歌名
        public TextView music_artist; //艺术家
        public TextView music_duration; //歌曲时长
        public TextView music_size; //歌曲大小
    }
    //适配器
    private class MyAdapter extends BaseAdapter {
        private LayoutInflater mInflater;
        private Context context;
        private List<MusicInfo> musicList; //存放MusicInfo引用的集合
        private MusicInfo musicInfo;      //MusicInfo对象引用

        public MyAdapter(Context context, List<MusicInfo> musicList) {
            this.context = context;
            this.musicList = musicList;
            this.mInflater = LayoutInflater.from(context);
        }
        @Override
        public int getCount(){
            return musicList.size();
        }
        @Override
        public Object getItem(int position){
            return musicList.get(position);
        }
        @Override
        public long getItemId(int position){
            return position;
        }
        @Override
        public View getView(final int position, View convertView, ViewGroup parent){
            final ViewHolder holder;
            if(convertView == null){
                holder = new ViewHolder();
                //引入布局
                /**
                 * int resource:需要加载布局文件的id,将该布局文件加载到Activity中来操作
                 * ViewGroup root:需要附加到resource资源文件的根控件
                 * boolean attachToRoot:是否将root附加到布局文件的根视图上
                 */
                convertView = mInflater.inflate(R.layout.list_item, null);
                //实例化对象
                holder.listitem = (RelativeLayout) convertView.findViewById(R.id.RelativeLayout1);
                holder.albumImage = (ImageButton) convertView.findViewById(R.id.albumImage);
                holder.play_pause = (ImageButton) convertView.findViewById(R.id.play_pause);
                holder.music_title = (TextView) convertView.findViewById(R.id.music_title);
                holder.music_artist = (TextView) convertView.findViewById(R.id.music_artist);
                holder.music_duration = (TextView)convertView.findViewById(R.id.music_duration);
                holder.music_size = (TextView) convertView.findViewById(R.id.music_size);
                convertView.setTag(holder); //给View添加一个格外的数据
            }else{
                holder = (ViewHolder)convertView.getTag(); //通过getTag()将数据取出来
            }

            musicInfo = musicList.get(position);
            //给控件赋值,musicList
//            holder.albumImage.setImageResource(musicInfo.getAlbumId()); //显示专辑
            holder.music_title.setText(musicInfo.getTitle()+".mp3"); //显示歌名
            holder.music_artist.setText(musicInfo.getArtist()); //显示艺术家
            holder.music_duration.setText(MusicUtils.formatTime(musicInfo.getDuration())); //显示歌曲时长
            holder.music_size.setText(MusicUtils.toMB(musicInfo.getSize())); //显示歌曲大小

            //List的点击事件
            holder.albumImage.setTag(position);
            holder.albumImage.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
//                    Toast.makeText(MainActivity.this,"你点击了listitem"+((Integer)v.getTag()+1),Toast.LENGTH_SHORT).show();
                    itemClick(holder,(Integer)v.getTag());
                    notifyDataSetChanged();
                }
            });
            return convertView;
        }
    }
    //进度条事件响应
    private class SeekBarListener implements SeekBar.OnSeekBarChangeListener{
        @Override
        public void onProgressChanged(SeekBar seekBar, int i, boolean b) {

        }
        /*滚动时,应当暂停后台定时器*/
        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {
            isSeekBarChanging = true;
//            musicService.seekTo(seekBar.getProgress());
        }
        /*滑动结束后,重新设置值*/
        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {
            isSeekBarChanging = false;
        }
    }
    //list点击事件响应
    @SuppressLint("ResourceAsColor")
    private void itemClick(ViewHolder holder, int position) {
        music_pause.setVisibility(View.VISIBLE);
        music_play.setVisibility(View.GONE);

        Log.i("tag", "position:" + position);

        MusicInfo musicFile = musicList.get(position);

        if (position == music_position) { //选中当前歌曲
            if (isPlaying) { //播放
                holder.listitem.setBackgroundColor(R.color.colorAccent);
                holder.albumImage.setVisibility(View.GONE);
                holder.play_pause.setVisibility(View.VISIBLE);
                musicService.pause();
                isPlaying = false;
            } else { //暂停
                holder.listitem.setBackgroundColor(R.color.colorAccent);
                holder.albumImage.setVisibility(View.VISIBLE);
                holder.play_pause.setVisibility(View.GONE);
                musicService.start();
                isPlaying = true;
            }
        }else { //选中其他歌曲
            holder.listitem.setBackgroundColor(R.color.colorAccent);
            holder.albumImage.setVisibility(View.GONE);
            holder.play_pause.setVisibility(View.VISIBLE);
            musicService.musicPlay(musicFile.getUrl()); //musicService.musicPlay
            play_title.setText(musicFile.getTitle());
            play_artist.setText(musicFile.getArtist());
        }
        music_position = position;
    }
    //按钮事件响应
    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.music_list:
                if (isShowOrNot == false) {
                    list_view.setVisibility(View.GONE);
                    surf_view.setVisibility(View.VISIBLE);
                    isShowOrNot = true;
                    Log.i("tag","音乐列表显示");
                } else {
                    list_view.setVisibility(View.VISIBLE);
                    surf_view.setVisibility(View.GONE);
                    isShowOrNot = false;
                    Log.i("tag","音乐列表隐藏");
                }
                Log.i("tag","打开音乐列表");
                break;
            case R.id.music_previous:
                Log.i("tag","快退");
                currentPositon = musicService.getCurrentPosition();
                if (currentPositon-10000>0){
                    musicService.seekTo(currentPositon-10000);
                }
                break;
            case R.id.music_play:
                music_pause.setVisibility(View.VISIBLE);
                music_play.setVisibility(View.GONE);
                musicService.start();
                Log.i("tag","开始播放音乐");
                break;
            case R.id.music_pause:
                music_pause.setVisibility(View.GONE);
                music_play.setVisibility(View.VISIBLE);
                musicService.pause();
                Log.i("tag","音乐暂停");
                break;
            case R.id.music_next:
                Log.i("tag","快进");
                currentPositon = musicService.getCurrentPosition();
                if (currentPositon+10000<musicService.getDuration()){
                    musicService.seekTo(currentPositon+10000);
                }
                break;
            case R.id.music_stop:
                music_pause.setVisibility(View.GONE);
                music_play.setVisibility(View.VISIBLE);
                //停止的时候将播放时间设置为初始值,进度条设置为初始位置
                seekbar.setProgress(0);
                musicService.stop();
                Log.i("tag","音乐停止");
                break;
        }
    }
    //解除绑定
    @Override
    protected void onDestroy() {
        super.onDestroy();
        musicService.stop();
        unbindService(serviceConnection);
        isPlaying = false;
    }
    //音乐播放指引
    Handler handler = new Handler();
    Runnable updateThread = new Runnable() { //使用线程循环更新当前播放进度,即更新进度条
        @Override
        public void run() {
            Time progress = new Time(musicService.getCurrentPosition());
            Time allTime = new Time(musicService.getDuration());
            String play_timeStr = progress.toString();
            Log.v("progress", play_timeStr);
            String all_timeStr = allTime.toString();
            play_time.setText(play_timeStr.substring(play_timeStr.indexOf(":") + 1));
            all_time.setText(all_timeStr.substring(all_timeStr.indexOf(":") + 1));
//            seekbar.setProgress(musicService.getCurrentPosition());
            int progressValues=0;
            if (musicService.getDuration()>0){
                progressValues=seekbar.getMax()*musicService.getCurrentPosition()/musicService.getDuration();
            }
            seekbar.setProgress(progressValues);
            handler.postDelayed(updateThread,400);
            if(isPlaying){
                MusicInterface(3,2,musicList);
            }
        }
    };
    //播放模式
    private final int PREVIOUS_MUSIC = 1;     //上一首
    private final int NEXT_MUSIC = 2;         //下一首
    private final int LOOP_MODE = 3;          //循环播放
    private final int RANDOM_MODE = 4;        //随机播放
    private void MusicInterface(int mode,int msg,List<MusicInfo> musicList){
        switch (mode){  //对当前的播放模式作出判断,进行不同的处理
            case LOOP_MODE: //循环模式
                switch (msg) {
                    case NEXT_MUSIC: //下一首,注意判断是否是最后一首了
                        if(music_position < musicList.size() - 1) {
                            music_position++;
                        }else {
                            Toast.makeText(this,"已经是最后一首了",Toast.LENGTH_SHORT).show();
                            music_position = 0;
                            handler.removeCallbacks(updateThread);
                            musicService.musicPlay(musicList.get(music_position).getUrl());
                            play_title.setText(musicList.get(music_position).getTitle());
                        }
                        break;
                    case PREVIOUS_MUSIC: //上一首,注意判断是否是第一首了
                        if(music_position >= 1) {
                            music_position--;
                        }else {
                            Toast.makeText(this, "已经是第一首了", Toast.LENGTH_SHORT).show();
                            music_position = musicList.size() - 1;
                            handler.removeCallbacks(updateThread);
                            musicService.musicPlay(musicList.get(music_position).getUrl());
                            play_title.setText(musicList.get(music_position).getTitle());
                        }
                        break;
                }
                break;
            case RANDOM_MODE: //随机模式,注意不要出界
                music_position = (int)(Math.random() * (musicList.size() - 1));
                break;
        }
        try{  //重新初始化一个service,将切换到的歌曲信息传给service
            MusicInfo musicInfo = musicList.get(music_position);
            String url = musicInfo.getUrl();

            play_title.setText(musicInfo.getTitle());
            seekbar.setMax(musicInfo.getDuration());

            musicService.musicPlay(url);
        }
        catch(Exception e){
            e.printStackTrace();
        }
    }
}

MusicService音乐服务:

/**
 * Created by Admin on 2018/5/4.
 */

public class MusicService extends Service{
    public MediaPlayer player; //声明 MediaPlayer 对象
    private MediaController controller; //声明 MediaController 对象

    @Override
    public IBinder onBind(Intent arg0) {
        Log.i("tag","onBind");
        controller = new MediaController();
        return controller;
    }
    @Override
    public void onCreate() {
        Toast.makeText(this,"MusicSeivice onCreate",Toast.LENGTH_SHORT).show();
        player = MediaPlayer.create(getApplicationContext(),R.raw.music); //默认读取音频
        if (player == null){
            Log.i("MusicSeivice","------null");
        }
        player.setLooping(true); //设置可以重复播放
        super.onCreate();
    }
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("MusicSeivice","onStartCommand");
        new Thread(new Runnable() {
            @Override
            public void run() {
                player.start();
                while (true) {
                    if (player == null || player.isPlaying() == false) {
                        stopSelf();
                        Log.i("MusicSeivice", "stopSelf()");
                        return;
                    }
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
        return super.onStartCommand(intent, flags, startId);
    }
    //播放
    public void start(){
        Log.i("tag","start");
        player.start();
    }
    //暂停
    public void pause(){
        Log.i("tag","pause");
        if (player != null && player.isPlaying()) {
            player.pause();
        }
    }
    //停止
    public void stop(){
        Log.i("tag","stop");
        player.stop();
        try {
            player.prepare();
        } catch (IOException e) {
            e.printStackTrace();
        }
        player.seekTo(0);
    }
    //缓冲
    public void prepare(){
        Log.i("tag","prepare");
        try {
            player.prepare();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //重置
    public void reset(){
        Log.i("tag","reset");
        player.reset();
    }
    //进度
    public void seekTo(int position){
        Log.i("tag","seekTo");
        player.seekTo(position);
    }
    //是否播放
    public boolean isPlaying(){
        Log.i("tag","isPlaying");
        return player.isPlaying();
    }
    //解绑服务
    @Override
    public void onDestroy() {
        Log.i("","onDestroy");
        player.stop();
        player.release();
        super.onDestroy();
    }
    //当前音乐的总时长
    public int getDuration() {
        return player.getDuration();
    }
    //当前播放的位置
    public int getCurrentPosition() {
        return player.getCurrentPosition();
    }
    //读取资源
    public void setDataSource(String path){
        try {
            player.setDataSource(path);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //MediaController
    class MediaController extends Binder {
        //返回MusicService实例
        public MusicService getService(){
            return MusicService.this;
        }
    }
    //开始播放
    public void musicPlay(String path) {
        try {
            player.reset(); //重置
            player.setDataSource(path);
            player.prepare(); //进行缓冲
            Log.i("tag", "缓冲完成");
            player.setOnPreparedListener(new PreparedListener()); //缓冲完成后执行
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    private final class PreparedListener implements MediaPlayer.OnPreparedListener {
        @Override
        public void onPrepared(MediaPlayer mediaPlayer) {
            mediaPlayer.start();
            Log.i("tag", "//start()执行");
        }
    }
}

MusicInfo音乐信息实体类:

/**
 * 歌曲信息实体类
 * Created by Admin on 2018/5/6.
 */

public class MusicInfo {
    private long id; // 歌曲ID 3
    private String title; // 歌曲名称 0
    private String album; // 专辑 7
    private int albumId;// 专辑ID 6
    private String displayName; // 显示名称 4
    private String artist; // 歌手名称 2
    private int duration; // 歌曲时长 1
    private int size; // 歌曲大小 8
    private String url; // 歌曲路径 5
    private String lrcTitle; // 歌词名称
    private String lrcSize; // 歌词大小

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getAlbum() {
        return album;
    }

    public void setAlbum(String album) {
        this.album = album;
    }

    public int getAlbumId() {
        return albumId;
    }

    public void setAlbumId(int albumId) {
        this.albumId = albumId;
    }

    public String getDisplayName() {
        return displayName;
    }

    public void setDisplayName(String displayName) {
        this.displayName = displayName;
    }

    public String getArtist() {
        return artist;
    }

    public void setArtist(String artist) {
        this.artist = artist;
    }

    public int getDuration() {
        return duration;
    }

    public void setDuration(int duration) {
        this.duration = duration;
    }

    public int getSize() {
        return size;
    }

    public void setSize(int size) {
        this.size = size;
    }

    public String getLrcTitle() {
        return lrcTitle;
    }

    public void setLrcTitle(String lrcTitle) {
        this.lrcTitle = lrcTitle;
    }

    public String getLrcSize() {
        return lrcSize;
    }

    public void setLrcSize(String lrcSize) {
        this.lrcSize = lrcSize;
    }
}

13. MusicUtils音乐工具类:(包含了媒体库读取歌词信息、时间处理、文件大小处理)

/**
 * 音乐工具类
 * Created by Admin on 2018/5/6.
 */

public class MusicUtils {
    //读取方法:读取SD卡里的歌曲信息,保存在List当中,以供Adapter调用显示
    public static List<MusicInfo> getMusicData(Context context){
        //生成动态数组,并转载数据
        List<MusicInfo> musicList = new ArrayList<MusicInfo>();
        /**
         * 媒体库查询语句,查询所有的歌曲
         * 参数:
         * Uri:提供内容的Provider标识,查询路径
         * projection:告诉Provider要返回的内容(列Column),如果填null,则返回所有列
         * selection:设置条件(相当于SQL语句中的where,null表示不进行筛选)
         * selectionArgs:查询条件属性值,(配合第三个参数使用,如果在第三个参数里面有?,那么在selectionArgs写的数据就会替换掉?)
         * sortOrder:按照什么进行排序,null则不进行排序
         */
        ContentResolver mResolver = context.getContentResolver();
        //MediaStore.Audio.Media.EXTERNAL_CONTENT_URI=="//media/external/audio/media"
        Cursor cursor = mResolver.query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
                null, null, null, null);
        Log.i("tag", "cursor:"+ cursor.getCount());
        Log.i("tag", "url:"+ MediaStore.Audio.Media.EXTERNAL_CONTENT_URI);
        //返回查询结果
        if(cursor != null) {
            cursor.moveToFirst();
            for (int i = 0; i < cursor.getCount(); i++) {
                Log.i("tag", "TITLE:"+ cursor.getString((cursor.
                        getColumnIndex(MediaStore.Audio.Media.TITLE))));
                Log.i("tag", "ARTIST:"+ cursor.getString((cursor.
                        getColumnIndex(MediaStore.Audio.Media.ARTIST))));

                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)); //专辑
                String displayName = cursor.getString(cursor
                        .getColumnIndex(MediaStore.Audio.Media.DISPLAY_NAME)); //显示歌名
                int albumId = cursor.getInt(
                        cursor.getColumnIndex(MediaStore.Audio.Media.ALBUM_ID)); //专辑ID
                int duration = cursor.getInt(cursor
                        .getColumnIndex(MediaStore.Audio.Media.DURATION)); // 时长
                int size = cursor.getInt(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(artist.equals("") || artist.equals("<unknown>")){
                    artist = "未知艺术家";
                }
                if (isMusic != 0) { // 只把音乐添加到集合当中
                    MusicInfo musicInfo = new MusicInfo();

                    musicInfo.setId(id);
                    musicInfo.setTitle(title);
                    musicInfo.setArtist(artist);
                    musicInfo.setAlbum(album);
                    musicInfo.setAlbumId(albumId);
                    musicInfo.setDisplayName(displayName);
                    musicInfo.setDuration(duration);
                    musicInfo.setSize(size);
                    musicInfo.setUrl(url);

                    cursor.moveToNext(); //游标移动

                    musicList.add(musicInfo); //把音乐加到List集合上
                }
            }
            cursor.close(); // 释放资源
        }
        return musicList;
    }
    // 时间转化处理,将时间修改为常用的格式
    public static String formatTime(int time){
        String minute = time / (1000 * 60) + "";
        String second = time % (1000 * 60) + "";
        if(minute.length() < 2){
            minute = "0" + (time / (1000 * 60)) + "";
        }else {
            minute = time / (1000 * 60) + "";
        }
        if(second.length() == 4){
            second = "0" + (time % (1000 * 60)) + "";
        }else if(second.length() == 3){
            second = "00" + (time % (1000 * 60)) + "";
        }else if(second.length() == 2){
            second = "000" + (time % (1000 * 60)) + "";
        }else if(second.length() == 1){
            second = "0000" + (time % (1000 * 60)) + "";
        }
        return minute + ":" + second.trim().substring(0, 2);
    }
    // 文件大小转换处理,将B转换为MB
    public static String toMB(int size) {
        float a = (float) size / (float) (1024 * 1024);
        String b = Float.toString(a);
        int c = b.indexOf(".");
        String fileSize = "";
        fileSize += b.substring(0, c + 2);
        return fileSize + "MB";
    }
}

顶 0踩 0收藏
文章评论
    发表评论

    个人资料

    • 昵称: 云代码会员
    • 等级: 初级程序员
    • 积分: 10
    • 代码: 0 个
    • 文章: 2 篇
    • 随想: 0 条
    • 访问: 0 次
    • 关注

    人气代码

      标签

      最新提问

        站长推荐