Android第八讲——多媒体(一) 音乐播放器

这里写图片描述
使用MediaPlayer对音频、视频操作:
如何获得MediaPlayer的对象
可以使用直接new的方式:
MediaPlayer mp = new MediaPlayer();
也可以使用create的方式,如:
MediaPlayer mp = MediaPlayer.create(this, R.raw.test);//这时就不用调用setDataSource了

音乐播放器

搭建主界面
现在AndroidManifest中添加权限
< uses-permission android:name=”android.permission.READ_EXTERNAL_STORAGE” />
xml中包括展示歌曲内容的ListView、进度条SeekBar、歌曲当前时间、歌曲总时间以及暂停/播放、上一曲、下一曲

<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"
    tools:context=".MainActivity"
    android:background="@mipmap/guide_background">
    <ListView
        android:id="@+id/listview_music"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1">

    </ListView>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:gravity="center">
            <TextView
                android:id="@+id/textview_music_currentposition"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="00:00"
                android:textColor="@android:color/darker_gray"
               />
            <SeekBar
                android:id="@+id/seekbar_music"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_weight="1" />
            <TextView
                android:id="@+id/textview_music_duration"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="00:00"
                android:textColor="@android:color/darker_gray"
                android:layout_alignParentRight="true"/>
        </LinearLayout>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:gravity="center">
            <ImageView
                android:layout_width="40dp"
                android:layout_height="40dp"
                />
            <ImageView
                android:id="@+id/imageview_music_play_prev"
                android:layout_width="45dp"
                android:layout_height="45dp"
                android:layout_marginRight="10dp"
                android:src="@mipmap/img_appwidget_play_prev"/>
            <ImageView
                android:id="@+id/imageview_music_playorpause"
                android:layout_width="50dp"
                android:layout_height="50dp"
                android:src="@mipmap/img_appwidget_play"/>
            <ImageView
                android:id="@+id/imageview_music_play_next"
                android:layout_width="45dp"
                android:layout_height="45dp"
                android:layout_marginLeft="10dp"
                android:src="@mipmap/img_appwidget_play_next"/>
        </LinearLayout>

    </LinearLayout>

</LinearLayout>

给每首歌曲设置布局格式 item_music_listview.xml

<?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="horizontal">
    <LinearLayout
        android:id="@+id/linearlayout_item"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <!-- 歌曲图片,暂时缺省,使用默认-->
        <ImageView
            android:id="@+id/imageview_music"
            android:layout_width="70dp"
            android:layout_height="70dp"
            android:src="@mipmap/img_background_appwidget91_default"/>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">
            <TextView
                android:id="@+id/textview_music_name"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="7dp"
                android:layout_marginLeft="10dp"
                android:text="歌曲名"
                android:textSize="18sp"/>
            <!-- 艺术家、暂时缺省-->
            <TextView
                android:id="@+id/textview_music_artist"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="15dp"
                android:layout_marginLeft="10dp"
                android:text=""/>

        </LinearLayout>

    </LinearLayout>

</LinearLayout>

创建一个歌曲类 MyMusic
类中包含歌曲的名称,歌曲的路径

/**
 * 歌曲类
 * Created by Went_Gone on 2015/9/10.
 */
public class MyMusic {
    private String musicName;
    private String path;

    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }

    public String getMusicName() {
        return musicName;
    }

    public void setMusicName(String musicName) {
        this.musicName = musicName;
    }
    MediaMetadataRetriever mmr;
    public MyMusic(String path) {
        File file = new File(path);
        musicName = file.getName();
    }
}

在MianActivity中先遍历Music中所有的音乐,将其添加到ListView中(此时需要Adapter)

mMyMusics = new ArrayList<>();//初始化
initMusic();
        mMusicAdapter = new MusicAdapter(mMyMusics, getLayoutInflater());
        mListView.setAdapter(mMusicAdapter);

    private void initMusic() {
        File sdcard = Environment.getExternalStorageDirectory();//找到手机Sdcard
        File music = new File(sdcard, "/Music");//拼音乐所在的文件夹
        musics = music.listFiles();//遍历音乐文件夹中的文件
        for (File musicl : musics){
            Log.d("Music",musicl.getAbsolutePath());
            MyMusic myMusic = new MyMusic(musicl.getAbsolutePath());
            mMyMusics.add(myMusic);
        }
    }

创建一个ListView 的Adapter MusicAdapter.java

/**
 * Created by Went_Gone on 2015/9/10.
 */
public class MusicAdapter extends BaseAdapter {
    private List<MyMusic> myMusics;
    private LayoutInflater mInflater;
    private String[] title;

    public MusicAdapter(List<MyMusic> myMusics, LayoutInflater mInflater) {
        this.myMusics = myMusics;
        this.mInflater = mInflater;
    }

    @Override

    public int getCount() {
        return myMusics.size();
    }

    @Override
    public Object getItem(int position) {
        return position;
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        MyMusic myMusic = myMusics.get(position);
        ViewHolder vh = null;
        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.item_music_listview, null);
            vh = new ViewHolder();
            vh.textViewMusicName = (TextView) convertView.findViewById(R.id.textview_music_name);
            vh.imageViewMusic = (ImageView) convertView.findViewById(R.id.imageview_music);
            vh.textViewMusicArtist = (TextView) convertView.findViewById(R.id.textview_music_artist);
            convertView.setTag(vh);
        }
        vh = (ViewHolder) convertView.getTag();
        vh.textViewMusicName.setText(myMusic.getMusicName());
        vh.imageViewMusic.setImageResource(R.mipmap.img_background_appwidget91_default);
        return convertView;
    }

    class ViewHolder {
        TextView textViewMusicName;
        ImageView imageViewMusic;
        TextView textViewMusicArtist;
    }
}

此时布局以及音乐都加载到了主界面上,接下来就是让音乐播放了
音乐该怎么播放呢,通过上边一开始的图可以知道大体步骤,先重置,找到要播放的音乐,准备,播放。我们不可能在播放的时候永远打开着界面,如果音乐播放的线程放在UI线程中,假使我们关闭主界面,音乐的线程很可能会被关闭掉。所以我们要尽可能不要让其关闭,所以我们将音乐播放的线程放在“Service(服务)”中去。另外,给ListView添加一个item点击事件,使得点击某首音乐时播放。
关于setOnItemClickListener 现在点击某一首音乐后,向MusicService中发送一个Intent,内部有音乐当前类型(是播放还是暂停还是上、下一曲)由MusicService进行解析判断

 mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Intent intent = new Intent(getApplicationContext(), MusicService.class);
                intent.putExtra(Config.MUSIC_STATE_TYPE,Config.MUSIC_NEW_START);
                intent.putExtra(Config.MUSIC_NAME, musics[position].getAbsolutePath());
                musicPosition = position;
                startService(intent);
                mImageViewPlay.setImageResource(R.mipmap.img_appwidget_pause);
            }
        });

MusicService中复写方法。要开一个线程,用来给UI线程发送广播,以便于将音乐的进度赋值给进度条。
MusicService中复写方法。要开一个线程,用来给UI线程发送广播,以便于将音乐的进度赋值给进度条。

    class MyMusicThread extends Thread{
        @Override
        public void run() {
            while(player.isPlaying()) {
                int currentPosition = player.getCurrentPosition();//得到当前音乐当前播放的时间

                //给Activity发送广播,以便于seekBar设置当前进度
                Intent intent = new Intent(Config.REGISTER_RECEIVER);
                intent.putExtra(Config.TYPE, Config.MUSIC_CURRENT);
                intent.putExtra(Config.CURRENTPOSITIO, currentPosition);
                sendBroadcast(intent);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

MainActivity中接收广播,用于设置SeekBar的值和音乐总时间及当前播放到的时间

 class MyMusicReceiver extends BroadcastReceiver{
        @Override
        public void onReceive(Context context, Intent intent) {
            int type = intent.getIntExtra(Config.TYPE,0);
            switch (type){
                case Config.MUSIC_DURATION:
                    int duration = intent.getIntExtra(Config.DURATION,0);
                    mSeekBar.setMax(duration);
                    SimpleDateFormat format = new SimpleDateFormat("mm:ss");
                    String time = format.format(new Date(duration));
                    mTextViewDuration.setText(""+time);
                    break;
                case Config.MUSIC_CURRENT:
                    int current = intent.getIntExtra(Config.CURRENTPOSITIO,0);
                    mSeekBar.setProgress(current);
                    SimpleDateFormat format1 = new SimpleDateFormat("mm:ss");
                    String time1 = format1.format(new Date(current));
                    mTextViewCurrent.setText(""+time1);
                    break;
                case Config.MUSIC_PAUSE:
                    mImageViewPlay.setImageResource(R.mipmap.img_appwidget_play);
                    break;
                case Config.MUSIC_START:
                    mImageViewPlay.setImageResource(R.mipmap.img_appwidget_pause);
                    break;
                default:
                    break;
            }
        }
    }

现在点击某一首音乐后,向MusicService中发送一个Intent,内部有音乐当前类型(是播放还是暂停还是上、下一曲)由MusicService进行解析判断
MusicService中的onStartCommand方法中
首先解析是哪种类型

int type = intent.getIntExtra(Config.MUSIC_STATE_TYPE,Config.MUSIC_NEW_START);
 case Config.MUSIC_NEW_START:
            //开始播放一首音乐
                startNewMusic(intent);
                break;

    /**
     * 开始一首新音乐
     * @param intent Activity传过来的Intent
     */
    private void startNewMusic(Intent intent) {
        String musicPath = intent.getStringExtra(Config.MUSIC_NAME);
        if (player == null) {
            player = new MediaPlayer();
        }
        player.reset();
        try {
            player.setDataSource(musicPath);
            player.prepare();
        } catch (IOException e) {
            e.printStackTrace();
        }
        player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
            @Override
            public void onPrepared(MediaPlayer mp) {
                mp.start();

                int duration = player.getDuration();//得到当前音乐的总时长
                Intent intent = new Intent(Config.REGISTER_RECEIVER);
                intent.putExtra(Config.TYPE, Config.MUSIC_DURATION);
                intent.putExtra(Config.DURATION,duration);
                sendBroadcast(intent);

                MyMusicThread musicThread = new MyMusicThread();
                musicThread.start();//开启线程为了实时传递歌曲播放进度

            }
        });
    }

当音乐播放时就需要有时暂停,有时播放
在Activity中通过点击向Service发送一个Intent,包含类型(暂停/播放)

            case R.id.imageview_music_playorpause:
                Intent intent = new Intent(getApplicationContext(),MusicService.class);
                intent.putExtra(Config.MUSIC_STATE_TYPE,Config.MUSIC_PAUSE_OR_START);
                startService(intent);
                break;

在Service中解析类型,在通过判断歌曲是否在播放。

1>如果在播放那么将它暂停,并且发送给Activity一个广播,将暂停/播放的图片重置一下。

2>如果是暂停的,难么放它播放,并且要讲设置SeekBar的线程开起来。

            case Config.MUSIC_PAUSE_OR_START:
                //暂停或者播放
                startOrPauseMusic();
                break;

    /**
     * 开始或暂停一首歌曲
     */
    private void startOrPauseMusic() {
        if (player!=null){
            if (player.isPlaying()){
                player.pause();
                Intent intent1 = new Intent(Config.REGISTER_RECEIVER);
                intent1.putExtra(Config.TYPE,Config.MUSIC_PAUSE);
                sendBroadcast(intent1);
            }else {
                player.start();
                Intent intent1 = new Intent(Config.REGISTER_RECEIVER);
                intent1.putExtra(Config.TYPE,Config.MUSIC_START);
                sendBroadcast(intent1);
                MyMusicThread thread = new MyMusicThread();
                thread.start();
            }
        }
    }

只是暂停或播放是不够的,我们设置了进度条,能够显示歌曲的进度,那么如果我们想通过进度条设置歌曲进度怎么办呢?
此时就需要在Seekbar上添加事件监听,当滑动SeekBar后,给Service发送一个Intent将滑动的位置传递过去,让歌曲在此位置上播放
首先是SeekBar

        mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {

            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }
            //当手机滑动结束并离开屏幕时
            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                Intent intent = new Intent(getApplicationContext(),MusicService.class);
                intent.putExtra(Config.MUSIC_STATE_TYPE,Config.MUSIC_SEEK_TO);
                intent.putExtra(Config.PROGRESS,mSeekBar.getProgress());
                startService(intent);
            }
        });

然后Service,解析类型

            case Config.MUSIC_SEEK_TO:
                int progress = intent.getIntExtra(Config.PROGRESS,0);
                if (player!=null) {
                    player.seekTo(progress);//将歌曲移动到进度条所显示的进度上
                }
                break;

我们平时用的音乐播放器是不是还有上、下一首呀
我们将上下一首也添加上去,这时我们就需要分类了。
1.如果我们点击了上一首该怎么办?

            case R.id.imageview_music_play_prev:
                //当点击上一首按钮时
                Intent intent1 = new Intent(getApplicationContext(),MusicService.class);
                intent1.putExtra(Config.MUSIC_STATE_TYPE,Config.MUSIC_PREV);
                if (musicPosition!=0) {
                    intent1.putExtra(Config.MUSIC_NAME, musics[musicPosition-1].getAbsolutePath());
                    musicPosition--;
                }else {
                    //如果当前播放音乐在第一首,那么在点击上一首就会跳转到最后一首
                    musicPosition = musics.length;
                    intent1.putExtra(Config.MUSIC_NAME, musics[musicPosition-1].getAbsolutePath());
                    musicPosition--;
                }
                startService(intent1);

2.当点击下一首时

            case R.id.imageview_music_play_next:
                //当点击下一首时
                Intent intent2 = new Intent(getApplicationContext(),MusicService.class);
                intent2.putExtra(Config.MUSIC_STATE_TYPE,Config.MUSIC_NEXT);
                if (musicPosition!=musics.length-1) {
                    intent2.putExtra(Config.MUSIC_NAME, musics[musicPosition+1].getAbsolutePath());
                    musicPosition++;
                }else {
                    //如果当前播放音乐在最后一首,那么在点击下一首就会跳转到第一首
                    musicPosition = 0;
                    intent2.putExtra(Config.MUSIC_NAME, musics[musicPosition].getAbsolutePath());
                    musicPosition++;
                }
                startService(intent2);

Activity将Intent传递到Service上,Service通过解析判断是上一首还是下一首

            case Config.MUSIC_PREV:
                //播放上一首
                if (player!=null){
                    startNewMusic(intent);
                }
                break;
            case Config.MUSIC_NEXT:
                //播放下一首
                if (player!=null){
                    startNewMusic(intent);
                }
                break;

好啦,现在一个简易的音乐播放器就做好了。后边我们还可以加入更多的功能,像随机播放啦、顺序播放啦…
运行如图:这里写图片描述

完整代码:
activity_main.xml

<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"
    tools:context=".MainActivity"
    android:background="@mipmap/guide_background">
    <ListView
        android:id="@+id/listview_music"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_weight="1">

    </ListView>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:gravity="center">
            <TextView
                android:id="@+id/textview_music_currentposition"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="00:00"
                android:textColor="@android:color/darker_gray"
               />
            <SeekBar
                android:id="@+id/seekbar_music"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_weight="1" />
            <TextView
                android:id="@+id/textview_music_duration"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="00:00"
                android:textColor="@android:color/darker_gray"
                android:layout_alignParentRight="true"/>
        </LinearLayout>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:gravity="center">
            <ImageView
                android:layout_width="40dp"
                android:layout_height="40dp"
                />
            <ImageView
                android:id="@+id/imageview_music_play_prev"
                android:layout_width="45dp"
                android:layout_height="45dp"
                android:layout_marginRight="10dp"
                android:src="@mipmap/img_appwidget_play_prev"/>
            <ImageView
                android:id="@+id/imageview_music_playorpause"
                android:layout_width="50dp"
                android:layout_height="50dp"
                android:src="@mipmap/img_appwidget_play"/>
            <ImageView
                android:id="@+id/imageview_music_play_next"
                android:layout_width="45dp"
                android:layout_height="45dp"
                android:layout_marginLeft="10dp"
                android:src="@mipmap/img_appwidget_play_next"/>
        </LinearLayout>

    </LinearLayout>

</LinearLayout>

item_music_listview.xml

<?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="horizontal">
    <LinearLayout
        android:id="@+id/linearlayout_item"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">
        <!-- 歌曲图片,暂时缺省,使用默认-->
        <ImageView
            android:id="@+id/imageview_music"
            android:layout_width="70dp"
            android:layout_height="70dp"
            android:src="@mipmap/img_background_appwidget91_default"/>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">
            <TextView
                android:id="@+id/textview_music_name"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="7dp"
                android:layout_marginLeft="10dp"
                android:text="歌曲名"
                android:textSize="18sp"/>
            <!-- 艺术家、暂时缺省-->
            <TextView
                android:id="@+id/textview_music_artist"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="15dp"
                android:layout_marginLeft="10dp"
                android:text=""/>

        </LinearLayout>

    </LinearLayout>

</LinearLayout>

MyMusic.java 音乐类

/**
 * 歌曲类
 * Created by Went_Gone on 2015/9/10.
 */
public class MyMusic {
    private String musicName;
    private String path;

    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }

    public String getMusicName() {
        return musicName;
    }

    public void setMusicName(String musicName) {
        this.musicName = musicName;
    }

    MediaMetadataRetriever mmr;
    public MyMusic(String path) {
        this.path = path;
        File file = new File(path);
        musicName = file.getName();
    }
}

MainActivity.java 主Activity

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private File[] musics;
    private List<MyMusic> mMyMusics;
    private ListView mListView;
    private MusicAdapter mMusicAdapter;
    private SeekBar mSeekBar;
    private MyMusicReceiver mReceiver;
    private TextView mTextViewDuration;
    private TextView mTextViewCurrent;
    private ImageView mImageViewPlay;
    private ImageView mImageViewPlayPrev;
    private ImageView mImageViewPlayNext;
    private int musicPosition = 0;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mListView = (ListView) findViewById(R.id.listview_music);
        mSeekBar = (SeekBar) findViewById(R.id.seekbar_music);
        mImageViewPlay = (ImageView) findViewById(R.id.imageview_music_playorpause);
        mTextViewDuration = (TextView) findViewById(R.id.textview_music_duration);
        mTextViewCurrent = (TextView) findViewById(R.id.textview_music_currentposition);
        mImageViewPlayPrev = (ImageView) findViewById(R.id.imageview_music_play_prev);
        mImageViewPlayNext = (ImageView) findViewById(R.id.imageview_music_play_next);
        mImageViewPlay.setOnClickListener(this);
        mImageViewPlayPrev.setOnClickListener(this);
        mImageViewPlayNext.setOnClickListener(this);

        mMyMusics = new ArrayList<>();//初始化
        initMusic();

        mMusicAdapter = new MusicAdapter(mMyMusics, getLayoutInflater());
        mListView.setAdapter(mMusicAdapter);
        mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Intent intent = new Intent(getApplicationContext(), MusicService.class);
                intent.putExtra(Config.MUSIC_STATE_TYPE,Config.MUSIC_NEW_START);
                intent.putExtra(Config.MUSIC_NAME, musics[position].getAbsolutePath());
                musicPosition = position;
                startService(intent);
                mImageViewPlay.setImageResource(R.mipmap.img_appwidget_pause);
            }
        });

        //注册广播
        mReceiver = new MyMusicReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction(Config.REGISTER_RECEIVER);
        registerReceiver(mReceiver, filter);

        mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {

            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }
            //当手机滑动结束并离开屏幕时
            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                Intent intent = new Intent(getApplicationContext(),MusicService.class);
                intent.putExtra(Config.MUSIC_STATE_TYPE,Config.MUSIC_SEEK_TO);
                intent.putExtra(Config.PROGRESS,mSeekBar.getProgress());
                startService(intent);
            }
        });
    }

    private void initMusic() {
        File sdcard = Environment.getExternalStorageDirectory();//找到手机Sdcard
        File music = new File(sdcard, "/Music");//拼音乐所在的文件夹
        musics = music.listFiles();//遍历音乐文件夹中的文件
        for (File musicl : musics){
            Log.d("Music",musicl.getAbsolutePath());
            MyMusic myMusic = new MyMusic(musicl.getAbsolutePath());
            mMyMusics.add(myMusic);
        }
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.imageview_music_playorpause:
                Intent intent = new Intent(getApplicationContext(),MusicService.class);
                intent.putExtra(Config.MUSIC_STATE_TYPE,Config.MUSIC_PAUSE_OR_START);
                startService(intent);
                break;
            case R.id.imageview_music_play_prev:
                //当点击上一首按钮时
                Intent intent1 = new Intent(getApplicationContext(),MusicService.class);
                intent1.putExtra(Config.MUSIC_STATE_TYPE,Config.MUSIC_PREV);
                if (musicPosition!=0) {
                    intent1.putExtra(Config.MUSIC_NAME, musics[musicPosition-1].getAbsolutePath());
                    musicPosition--;
                }else {
                    //如果当前播放音乐在第一首,那么在点击上一首就会跳转到最后一首
                    musicPosition = musics.length;
                    intent1.putExtra(Config.MUSIC_NAME, musics[musicPosition-1].getAbsolutePath());
                    musicPosition--;
                }
                startService(intent1);
                break;
            case R.id.imageview_music_play_next:
                //当点击下一首时
                Intent intent2 = new Intent(getApplicationContext(),MusicService.class);
                intent2.putExtra(Config.MUSIC_STATE_TYPE,Config.MUSIC_NEXT);
                if (musicPosition!=musics.length-1) {
                    intent2.putExtra(Config.MUSIC_NAME, musics[musicPosition+1].getAbsolutePath());
                    musicPosition++;
                }else {
                    //如果当前播放音乐在最后一首,那么在点击下一首就会跳转到第一首
                    musicPosition = 0;
                    intent2.putExtra(Config.MUSIC_NAME, musics[musicPosition].getAbsolutePath());
                    musicPosition++;
                }
                startService(intent2);
                break;
            default:
                break;
        }
    }

    class MyMusicReceiver extends BroadcastReceiver{
        @Override
        public void onReceive(Context context, Intent intent) {
            int type = intent.getIntExtra(Config.TYPE,0);
            switch (type){
                case Config.MUSIC_DURATION:
                    int duration = intent.getIntExtra(Config.DURATION,0);
                    mSeekBar.setMax(duration);
                    SimpleDateFormat format = new SimpleDateFormat("mm:ss");
                    String time = format.format(new Date(duration));
                    mTextViewDuration.setText(""+time);
                    break;
                case Config.MUSIC_CURRENT:
                    int current = intent.getIntExtra(Config.CURRENTPOSITIO,0);
                    mSeekBar.setProgress(current);
                    SimpleDateFormat format1 = new SimpleDateFormat("mm:ss");
                    String time1 = format1.format(new Date(current));
                    mTextViewCurrent.setText(""+time1);
                    break;
                case Config.MUSIC_PAUSE:
                    mImageViewPlay.setImageResource(R.mipmap.img_appwidget_play);
                    break;
                case Config.MUSIC_START:
                    mImageViewPlay.setImageResource(R.mipmap.img_appwidget_pause);
                    break;
                default:
                    break;
            }
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(mReceiver);
    }
}

MusicAdapter ListView的Adapter

/**
 * Created by Went_Gone on 2015/9/10.
 */
public class MusicAdapter extends BaseAdapter {
    private List<MyMusic> myMusics;
    private LayoutInflater mInflater;
    private String[] title;

    public MusicAdapter(List<MyMusic> myMusics, LayoutInflater mInflater) {
        this.myMusics = myMusics;
        this.mInflater = mInflater;
    }

    @Override

    public int getCount() {
        return myMusics.size();
    }

    @Override
    public Object getItem(int position) {
        return position;
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        MyMusic myMusic = myMusics.get(position);
        ViewHolder vh = null;
        if (convertView == null) {
            convertView = mInflater.inflate(R.layout.item_music_listview, null);
            vh = new ViewHolder();
            vh.linearLayoutItme = (LinearLayout) convertView.findViewById(R.id.linearlayout_item);
            vh.textViewMusicName = (TextView) convertView.findViewById(R.id.textview_music_name);
            vh.imageViewMusic = (ImageView) convertView.findViewById(R.id.imageview_music);
            vh.textViewMusicArtist = (TextView) convertView.findViewById(R.id.textview_music_artist);
            convertView.setTag(vh);
        }
        vh = (ViewHolder) convertView.getTag();
        vh.textViewMusicName.setText(myMusic.getMusicName());
        vh.imageViewMusic.setImageResource(R.mipmap.img_background_appwidget91_default);
        return convertView;
    }

    class ViewHolder {
        TextView textViewMusicName;
        ImageView imageViewMusic;
        TextView textViewMusicArtist;
        LinearLayout linearLayoutItme;
    }
}

MusicService.java Service(后台服务)

/**
 * Created by Went_Gone on 2015/9/10.
 */
public class MusicService extends Service {
    private MediaPlayer player;

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

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        int type = intent.getIntExtra(Config.MUSIC_STATE_TYPE,Config.MUSIC_NEW_START);
        switch (type){
            case Config.MUSIC_NEW_START:
            //开始播放一首音乐
                startNewMusic(intent);
                break;
            case Config.MUSIC_SEEK_TO:
                int progress = intent.getIntExtra(Config.PROGRESS,0);
                if (player!=null) {
                    player.seekTo(progress);//将歌曲移动到进度条所显示的进度上
                }
                break;
            case Config.MUSIC_PAUSE_OR_START:
                //暂停或者播放
                startOrPauseMusic();
                break;
            case Config.MUSIC_PREV:
                //播放上一首
                if (player!=null){
                    startNewMusic(intent);
                }
                break;
            case Config.MUSIC_NEXT:
                //播放下一首
                if (player!=null){
                    startNewMusic(intent);
                }
                break;
            default:
                break;
        }
        return super.onStartCommand(intent, flags, startId);
    }

    /**
     * 开始或暂停一首歌曲
     */
    private void startOrPauseMusic() {
        if (player!=null){
            if (player.isPlaying()){
                player.pause();
                Intent intent1 = new Intent(Config.REGISTER_RECEIVER);
                intent1.putExtra(Config.TYPE,Config.MUSIC_PAUSE);
                sendBroadcast(intent1);
            }else {
                player.start();
                Intent intent1 = new Intent(Config.REGISTER_RECEIVER);
                intent1.putExtra(Config.TYPE,Config.MUSIC_START);
                sendBroadcast(intent1);
                MyMusicThread thread = new MyMusicThread();
                thread.start();
            }
        }
    }

    /**
     * 开始一首新音乐
     * @param intent Activity传过来的Intent
     */
    private void startNewMusic(Intent intent) {
        String musicPath = intent.getStringExtra(Config.MUSIC_NAME);
        if (player == null) {
            player = new MediaPlayer();
        }
        player.reset();
        try {
            player.setDataSource(musicPath);
            player.prepare();
        } catch (IOException e) {
            e.printStackTrace();
        }
        player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
            @Override
            public void onPrepared(MediaPlayer mp) {
                mp.start();

                int duration = player.getDuration();//得到当前音乐的总时长
                Intent intent = new Intent(Config.REGISTER_RECEIVER);
                intent.putExtra(Config.TYPE, Config.MUSIC_DURATION);
                intent.putExtra(Config.DURATION,duration);
                sendBroadcast(intent);

                MyMusicThread musicThread = new MyMusicThread();
                musicThread.start();

            }
        });
    }

    class MyMusicThread extends Thread{
        @Override
        public void run() {
            while(player.isPlaying()) {
                int currentPosition = player.getCurrentPosition();//得到当前音乐当前播放的时间

                //给Activity发送广播,以便于seekBar设置当前进度
                Intent intent = new Intent(Config.REGISTER_RECEIVER);
                intent.putExtra(Config.TYPE, Config.MUSIC_CURRENT);
                intent.putExtra(Config.CURRENTPOSITIO, currentPosition);
                sendBroadcast(intent);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 使用Android Studio开发音乐播放器可以分为以下步骤: 1. 创建一个新的Android项目并命名为音乐播放器。这将自动生成一个项目的基本结构。 2. 在界面设计中,可以使用XML文件创建音乐播放器的用户界面。可以包含播放/暂停按钮、进度条、音乐列表、音乐封面图片等。 3. 在MainActivity.java文件中,编写逻辑代码来实现音乐播放器的各种功能。可以使用MediaPlayer类来控制音乐的播放、暂停、停止等操作。可以使用MediaMetadataRetriever类来获取音乐文件的元数据,如歌曲名称、艺术家、专辑等。 4. 在AndroidManifest.xml文件中添加必要的权限,如访问存储卡中的音乐文件、获取音乐文件的元数据等。 5. 为音乐播放器添加功能,如播放列表的显示与切换、音乐的循环播放、随机播放、进度条的更新、音乐封面的显示等。 6. 可以自定义音乐播放器的外观,如选择自定义主题颜色、更换播放控制按钮的图标等。 7. 添加额外的功能,如歌词显示、音乐搜索、推荐歌曲等。可以使用网络请求与服务器交互来获取歌曲信息。 8. 在发布之前,进行测试与调试,确保播放器的各项功能正常运行且无bug。 总结:使用Android Studio开发音乐播放器需要对XML界面设计、Java编程语言和Android SDK有一定的了解。通过合理地编写逻辑代码,可实现音乐的播放、暂停、停止等功能,同时可以根据需求对播放器进行定制。开发者还可以通过添加额外的功能提升用户体验,如歌词显示、音乐搜索等。开发完成后,进行测试与调试,确保功能正常运行。 ### 回答2: Android Studio是一款官方的Android开发集成开发环境(IDE),使用Java和Kotlin作为主要开发语言。要在Android Studio中开发一个音乐播放器,可以按照以下步骤进行: 1. 创建一个新的Android项目:打开Android Studio并选择“新建项目”,填写应用程序的名称和包名,选择适当的最低SDK版本等。 2. 布局设计:使用Android Studio的布局编辑器来设计音乐播放器的用户界面。您可以添加播放/暂停按钮、进度条、音频控制按钮等等,根据您的需求进行布局。 3. 添加音频文件:将音频文件添加到项目的资源目录中。您可以在代码中通过资源ID访问这些音频文件。 4. 媒体控制:在Java或Kotlin代码中实现音频播放控制逻辑。您可以使用Media Player类或ExoPlayer库来实现播放、暂停、停止等功能。还可以添加相应的回调方法来监听播放器状态的变化。 5. UI交互:为播放器UI中的各个元素添加交互功能。例如,当用户点击播放按钮时,播放器开始播放音乐;当用户拖动进度条时,播放器跳转到相应的时间点等。 6. 音频控制:实现音频控制功能,例如音量调节、播放模式切换(顺序播放、随机播放等)等。这可以通过修改播放器的相关属性来实现。 7. 错误处理和异常情况:在代码中添加错误处理和异常情况处理逻辑,例如处理音频加载失败、耗时操作中的UI线程阻塞等。 8. 测试和调试:使用Android Studio的调试工具来测试和调试您的应用程序,确保播放器在各种情况下都能正常工作。 9. 发布和部署:最后,您可以在Android Studio中生成一个APK文件,并将其发布到Google Play商店或其他应用商店中。 总结来说,开发一个音乐播放器需要通过创建项目、设计界面、添加音频文件、实现控制逻辑、添加交互功能、处理异常情况等步骤。Android Studio提供了强大的开发工具和库来支持您完成这些任务。 ### 回答3: Android Studio是一个非常强大的集成开发环境,可以用于开发各种类型的Android应用程序,包括音乐播放器。 首先,我们需要在Android Studio中创建一个新的项目。在创建项目时,我们可以选择一些基本的设置,比如应用程序的名称、包名等等。 接下来,我们需要添加一些必要的功能。首先,我们需要添加一个界面来显示音乐播放器的用户界面。我们可以使用XML布局来设计界面,并在代码中使用Java语言来控制布局和显示。 然后,我们需要添加音乐播放器的功能。这包括从存储设备或网络加载音乐文件、播放、暂停、停止音乐等操作。我们可以使用Java的MediaPlayer类来实现这些功能。 同时,我们可以添加一些额外的功能,如音乐列表、循环播放、随机播放、歌词显示等。这需要针对用户需求进行开发,并在代码中实现。 另外,我们还可以添加一些可视化效果,如音乐频谱、音乐可视化效果等。这可以通过使用Android的图形库来实现。 最后,我们需要进行测试和调试,以确保音乐播放器的正常运行。我们可以使用Android Studio提供的调试工具,并在不同的设备上进行测试,以确保应用程序的兼容性和稳定性。 总的来说,使用Android Studio开发一个音乐播放器需要熟悉Android开发技术和相关类库,同时需要进行设计、开发、测试和调试。这需要一定的时间和经验,但通过细心和努力,我们可以开发出一个功能完善的音乐播放器应用程序。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值