自己动手实现音乐播放器app

MainActivity实现:
1.调用TabHost绑定不同的tags,图标,和content。

mTabHost = (TabHost) findViewById(R.id.mTabHost);
        mTabHost.setup();
        for (int i = 0; i < titles.length; i++) {//循环添加选项卡
            TabHost.TabSpec tabSpec = mTabHost.newTabSpec(tags[i]);//创建一个选项,并指定其标记
            View view = getLayoutInflater().inflate(R.layout.tab, null);
            TextView titleView = (TextView) view.findViewById(R.id.title);
            ImageView iconView = (ImageView) view.findViewById(R.id.icon);
            titleView.setText(titles[i]);//设置标题
            iconView.setImageResource(icons[i]);//设置图标
            tabSpec.setIndicator(view);//为选项设置标题和图标
            tabSpec.setContent(R.id.realContent);//为每个选项设置内容
            mTabHost.addTab(tabSpec);//将选项添加到选项卡中
        }
        mTabHost.setOnTabChangedListener(new MyTabChangedListener());//添加选项改变事件处理
        mTabHost.setCurrentTab(1);//默认显示第二个

2.切换至不同的按钮时,用新创建的fragment替换之前设置的content,但是我始终没有解决切换fragment后,再回到原fragment状态依然不改变。我初步认定是切换不同tab时,系统会强制将当前创建的fragment销毁。
点击不同tab,显示不同fragemnt

public void onTabChanged(String tabTag){
fragmentTransaction = getFragemntManager().begingTransaction();
if(tabTag.equalsIgnoreCase("artist")){//切换到艺术家列表
fragmentTransaction.replace(R.id.realContent,new ArtistFragemnt());
}
fragmentTracsaction.commit();//提交事务
}

3.重写ondestroy方法,在退出前保存playlist中的数据

@Override
    protected void onDestroy() {//关闭的时候将播放列表中的数据保存到数据库
        mDatabase.execSQL("delete from music_tb");//删除已有的所有数据
        for (int i = 0; i < Constants.playlist.size(); i++) {//循环遍历播放列表中的音乐
            Music music = Constants.playlist.get(i);
            mDatabase.execSQL("insert into music_tb(title,artist,album,album_id,time,url)values(?,?,?,?,?,?)", new String[]{music.getTitle(), music.getSinger(), music.getAlbum(), music.getAlbum_id() + "", music.getTime() + "", music.getUrl()});
            //将音乐信息保存到数据库
        }
        super.onDestroy();
    }

定义一些常量

package com.example.zengqi.musicplayer;

import android.net.Uri;

import java.util.ArrayList;
import java.util.List;


public class Constants {
    public static List<Music> musicList = new ArrayList<>();//所有音乐的集合
    public static List<Music> playlist = new ArrayList<>();//音乐播放列表
    public static final String CONTROL_ACTION = "com.example.zengqi.control";//控制音乐播放动作,即播放或暂停
    public static final String SEEKBAR_ACTION = "com.example.zengqi.seekbar";//音乐进度发送变化动作
    public static final String COMPLETE_ACTION = "com.example.zengqi.complete";//音乐播放结束动作
    public static final String UPDATE_ACTION = "com.example.zengqi.update";//更新进度条
    public static final String UPDATE_STYLE = "com.example.zengqi.style";//更新播放形式

    public static final Uri ALBUM_URI = Uri.parse("content://media/external/audio/albumart");
    public static final String LIST_LOOP = "列表循环";
    public static final String SINGLE_LOOP = "单曲循环";
    public static final String OVER_FINISH = "结束后暂停";
    public static final String RANDOM_PLAY = "随机播放";

    public static final int NEW = 6;//开始一首新的音乐
    public static final int PLAY = 1;//播放
    public static final int PAUSE = 2;//暂停
    public static final int ALL_MUSIC = 0x11;//播放所有的音乐
    public static final int PLAY_LIST_MUSIC = 0x12;//播放播放列表中的音乐

}

重点是这里使用的musicList和playList,他们是全局状态下的变量,单例模式,用于在不同fragment间通信,所有fragment将值存入其中,同时也从中取值。

public static List<Music> getDataFromDB(SQLiteDatabase db) {
        //数据库中未存入size,name的信息
        //从数据库中获取播放列表的内容

        List<Music> musics = new ArrayList<>();
        Cursor cursor = db.rawQuery("select * from music_tb", null);
        if (cursor == null || cursor.getCount() == 0) {
            return null;
        }
        while (cursor.moveToNext()) {
            Music music = new Music();
            music.setTitle(cursor.getString(cursor.getColumnIndex("title")));
            music.setSinger(cursor.getString(cursor.getColumnIndex("artist")));
            music.setAlbum(cursor.getString(cursor.getColumnIndex("album")));
            music.setAlbum_id(cursor.getInt(cursor.getColumnIndex("album_id")));
            music.setUrl(cursor.getString(cursor.getColumnIndex("url")));
            music.setTime(cursor.getInt(cursor.getColumnIndex("time")));
            musics.add(music);
        }
        return musics;
    }

这里注意在每次调用该函数时,都应该检察其值是否为null,例如下面:

if(MusicUtils.getDataFromDB(mDatabase)==null){
            Constants.playlist = new ArrayList<>();
        }else{//if与else语法!!!小心!!!
            Constants.playlist = MusicUtils.getDataFromDB(mDatabase);//初始化播放列表
        }

这样playlist就被合理的初始化了,这样接下来就可以安心调用其方法了,而不会空指针异常。这里需要注意,if与else,我刚开始不够心细,只写了if,导致在从数据库中读取不到playlist的情况下,playlist永远不能够被初始化!

关于MusicService:

package com.example.zengqi.musicplayer;
import java.util.List;
import java.util.Random;
import java.util.Timer;
import java.util.TimerTask;

import android.app.Notification;
import android.app.Notification.Builder;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.graphics.BitmapFactory;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.os.IBinder;
public class MusicService extends Service {
    private List<Music> musicList;//音乐列表
    private int position;//当前音乐的序号
    private MediaPlayer mediaPlayer;//媒体播放器
    private ActivityReceiver activityReceiver;//广播接收器
    private Music currentMusic;//当前播放的音乐
    private Timer timer;//定时器
    private int listType;//列表的类型
    private String styleString=Constants.LIST_LOOP;//音乐播放形式,默认列表循环
    public void onCreate() {//启动服务
        mediaPlayer=new MediaPlayer();
        activityReceiver=new ActivityReceiver();
        IntentFilter filter=new IntentFilter();//创建Intent过滤器
        filter.addAction(Constants.CONTROL_ACTION);//控制音乐播放的动作,包括播放和暂停
        filter.addAction(Constants.SEEKBAR_ACTION);//改变音乐播放进度
        filter.addAction(Constants.UPDATE_STYLE);//改变音乐播放样式
        registerReceiver(activityReceiver, filter);//注册广播接收器
        super.onCreate();
    }
    public IBinder onBind(Intent intent) {
        return null;
    }
    private class ActivityReceiver extends BroadcastReceiver{//获取前台发送的广播
        public void onReceive(Context context, Intent intent) {
            if(intent.getAction()==Constants.CONTROL_ACTION){//接收到控制播放的广播(开始新音乐、暂停、播放)
                int isNew=intent.getIntExtra("new", -1);
                if(isNew!=-1){//播放一首新音乐
                    listType=intent.getIntExtra("listType",Constants.ALL_MUSIC);
                    if(listType==Constants.ALL_MUSIC){//如果是所有的音乐
                        musicList=Constants.musicList;
                    }else{//如果是播放列表
                        musicList=Constants.playlist;
                    }
                    position=intent.getIntExtra("position", 0);
                    currentMusic=musicList.get(position);//获取当前需要播放的音乐
                    preparedAndPlay(currentMusic);//准备并播放音乐
                }else{
                    int control=intent.getIntExtra("control",-1);
                    if(control==Constants.PAUSE){//表示要暂停音乐
                        mediaPlayer.pause();//音乐暂停
                        timer.cancel();//取消定时器
                    }else if(control==Constants.PLAY){//表示继续播放音乐
                        mediaPlayer.start();
                        startTimer();//启动定时器
                    }
                }
            }else if(intent.getAction()==Constants.SEEKBAR_ACTION){
                int progress=intent.getIntExtra("progress",0);//获取传递的进度
                int position=(int)(currentMusic.getTime()*progress*1.0/100);//将进度转换成相应的时间位置
                mediaPlayer.seekTo(position);//音乐跳转到指定位置继续播放
            }else if(intent.getAction()==Constants.UPDATE_STYLE){
                styleString=intent.getStringExtra("style");
                SharedPreferences musicPreferences=getSharedPreferences("music", Context.MODE_PRIVATE);
                Editor editor=musicPreferences.edit();//获取参数编辑器
                editor.putString("style", styleString);
                editor.commit();//提交数据
            }
        }
    }
    public void preparedAndPlay(Music music){// 准备并播放音乐
        try{
            mediaPlayer.reset();//重置媒体播放器
            mediaPlayer.setDataSource(music.getUrl());//设置音乐播放的路径
            mediaPlayer.prepare();// 准备播放音乐
            mediaPlayer.start();// 播放音乐
            startTimer();//启动定时器
            sendNotification();//发送广播
            saveInfo();//保存数据
            mediaPlayer.setOnCompletionListener(new OnCompletionListener() {//音乐播放结束事件监听器
                public void onCompletion(MediaPlayer mp) {//音乐播放完成后,根据设置的播放类型进行播放,并通知前台改变
                    if(!Constants.OVER_FINISH.equalsIgnoreCase(styleString)){//如果不是播放结束停止
                        if(Constants.LIST_LOOP.equalsIgnoreCase(styleString)){
                            position=(position+1)%musicList.size();//自动播放下一首
                        }else if(Constants.RANDOM_PLAY.equalsIgnoreCase(styleString)){
                            position=new Random().nextInt(musicList.size());
                        }
                        currentMusic=musicList.get(position);//获取当前的音乐
                        preparedAndPlay(currentMusic);//准备并播放音乐
                        Intent intent=new Intent(Constants.COMPLETE_ACTION);
                        intent.putExtra("position", position);
                        sendBroadcast(intent);//发送广播
                    }else{
                        stopSelf();//结束
                    }
                }
            });
        }catch(Exception ex){
            ex.printStackTrace();
        }
    }
    public void saveInfo(){//保存信息
        SharedPreferences musicPreferences=getSharedPreferences("music", Context.MODE_PRIVATE);
        Editor editor=musicPreferences.edit();//获取参数编辑器
        editor.putInt("listType",listType);//保存音乐列表类型
        editor.putInt("position",position);//保存音乐的位置
        editor.commit();//提交数据
    }
    public void sendNotification(){//后台发送通知
        NotificationManager notificationManager=(NotificationManager)getSystemService(Service.NOTIFICATION_SERVICE);//获取通知服务器
        Builder builder=new Notification.Builder(this);//通知构建器
        builder.setAutoCancel(false);//打开通知后自动消除为false
        builder.setTicker("音乐播放");//第一次出现时,显示在状态栏的通知提示信息
        builder.setSmallIcon(R.drawable.music);//设置通知的小图标
        builder.setLargeIcon(BitmapFactory.decodeResource(getResources(),R.drawable.largeicon));//设置通知的大图标
        builder.setContentTitle("正在播放音乐");//设置通知内容的标题
        builder.setContentText(currentMusic.getTitle()+" "+currentMusic.getSinger());//设置通知的内容
        Intent intent=new Intent("com.example.zengqi.music_play");//通知启动的页面
        PendingIntent pIntent=PendingIntent.getActivity(this,0, intent, 0);
        builder.setContentIntent(pIntent);//设置通知启动的程序
        notificationManager.notify(0x11, builder.build());//发送通知
    }
    public void startTimer(){//启动定时器
        timer=new Timer();//创建定时器对象
        timer.schedule(new TimerTask() {//定时执行的任务
            public void run() {//发送广播,通知更新前台进度条
                Intent updateIntent=new Intent(Constants.UPDATE_ACTION);
                updateIntent.putExtra("position", mediaPlayer.getCurrentPosition());
                sendBroadcast(updateIntent);
            }
        }, 0,1000);//每隔1秒发一次
    }
    public void onDestroy() {//服务销毁时调用该方法
        if(mediaPlayer!=null){//重置音乐播放器
            mediaPlayer.reset();
        }
        if(activityReceiver!=null){//取消广播接收器
            unregisterReceiver(activityReceiver);
        }
        super.onDestroy();
    }
}

关于MusicPlayActivity:

//package com.example.zengqi.musicplayer;
//
//import android.app.Activity;
//import android.content.BroadcastReceiver;
//import android.content.Context;
//import android.content.Intent;
//import android.content.IntentFilter;
//import android.content.SharedPreferences;
//import android.graphics.Bitmap;
//import android.os.Bundle;
//import android.os.PersistableBundle;
//import android.view.View;
//import android.view.Window;
//import android.view.WindowManager;
//import android.widget.AdapterView;
//import android.widget.ArrayAdapter;
//import android.widget.ImageButton;
//import android.widget.ImageView;
//import android.widget.SeekBar;
//import android.widget.Spinner;
//import android.widget.TextView;
//
//import java.util.List;
//
///**
// * Created by Administrator on 2015/10/23.
// */
//public class MusicPlayActivity extends Activity{
// //音乐的播放主界面,可控制音乐的播放
// private List<Music> musicList;//记录音乐列表
// //显示当前歌曲名,作者信息,当前播放时间,总时间的文本框
// private TextView titleView,singerView,currentTimeView,totalTimeView;
// private SeekBar playProgress;//拖动条
// private Spinner styleSpinner;//选择播放形式的下拉列表
// private ImageButton control;//播放和暂停按钮
// private ImageView picView;//显示图片
// private ServerReceiver serverReceiver;//接受后台服务发送的广播的广播接收器
// private Music currentMusic;//记录当前播放的音乐
// private boolean isPause = false;//是否暂停
// private int currentPosition;//当前音乐的索引
// private int listType;//音乐列表的类型,是播放所有音乐还是播放列表中的音乐
// private String[]styles = new String[]{Constants.LIST_LOOP,Constants.SINGLE_LOOP,Constants.RANDOM_PLAY,Constants.OVER_FINISH};
//
// @Override
// public void onCreate(Bundle savedInstanceState, PersistableBundle persistentState) {
// super.onCreate(savedInstanceState, persistentState);
// requestWindowFeature(Window.FEATURE_NO_TITLE);//去除标题
// getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);//全屏显示
// setContentView(R.layout.play_item);
// initView();//初始化界面
// }
//
// private void initView() {
// styleSpinner = (Spinner) findViewById(R.id.styleSpinner);
// styleSpinner.setAdapter(new ArrayAdapter<String>(this, R.layout.spinner_text, styles));
// styleSpinner.setOnItemSelectedListener(new SpinnerItemClickListener());
// picView = (ImageView) findViewById(R.id.picView);
// //显示当前音乐播放的时间进度
// currentTimeView = (TextView) findViewById(R.id.currentTime);
// totalTimeView = (TextView) findViewById(R.id.totalTime);
// titleView = (TextView) findViewById(R.id.title);
// singerView = (TextView) findViewById(R.id.singer);
// playProgress = (SeekBar) findViewById(R.id.playProgress);
// control = (ImageButton) findViewById(R.id.control);
// playProgress.setOnSeekBarChangeListener(new MyseekBarChangeListener());
// serverReceiver = new ServerReceiver();//创建广播接收器
// IntentFilter filter = new IntentFilter();//可以接受到的广播类型
// filter.addAction(Constants.COMPLETE_ACTION);//音乐播放结束的事件
// filter.addAction(Constants.UPDATE_ACTION);//更新进度的动作
// registerReceiver(serverReceiver,filter);//注册广播接收器
// currentMusic = (Music)getIntent().getSerializableExtra("music");//获取当前播放的音乐
// if(currentMusic==null){
// SharedPreferences musicPreferences = getSharedPreferences("music", Context.MODE_PRIVATE);
// currentPosition = musicPreferences.getInt("position",0);
// listType = musicPreferences.getInt("listType", Constants.ALL_MUSIC);
// if(listType==Constants.ALL_MUSIC){//若是所有的音乐
// musicList = Constants.musicList;
// }else{//若是列表音乐
// musicList = Constants.playlist;
// }
// currentMusic = musicList.get(currentPosition);//获取当前的音乐
// String styleString = musicPreferences.getString("style",Constants.LIST_LOOP);
// for (int i = 0; i < styles.length; i++) {
// if(styles[i].equalsIgnoreCase(styleString)){
// styleSpinner.setSelection(i);
// break;
// }
// }
// showInfo();//显示音乐信息
// isPause = true;//继续播放
// control(null);
// }else{//直接播放音乐
// currentPosition = getIntent().getIntExtra("position",0);//默认为第一首
// listType = getIntent().getIntExtra("listType",Constants.ALL_MUSIC);//获取播放的列表类型
// playNewMusic();//播放音乐
// if(listType==Constants.ALL_MUSIC){
// musicList = Constants.musicList;//所有音乐
// }else{
// musicList = Constants.playlist;//播放列表
// }
// }
// }
//
// public void showInfo(){
// totalTimeView.setText(MusicUtils.timeToString(currentMusic.getTime()));//显示音乐的总时长
// titleView.setText(" "+currentMusic.getTitle()+" ");//显示歌曲名
// singerView.setText(currentMusic.getSinger());//显示演唱者
// Bitmap bitmap = MusicUtils.getAlbumPic(this,currentMusic);
// if(bitmap!=null){
// picView.setImageBitmap(bitmap);
// }else{
// picView.setImageResource(R.drawable.background);
// }
// }
//
// public void playNewMusic(){
// currentTimeView.setText(MusicUtils.timeToString(0));//显示当前播放的时间,默认为0
// showInfo();
// playProgress.setProgress(0);//设置进度为0
// control.setImageResource(R.drawable.pause);//显示暂停的按钮
// //发送广播,通知后台播放音乐
// Intent controlIntent = new Intent(Constants.CONTROL_ACTION);
// controlIntent.putExtra("new",Constants.NEW);//这是一首新音乐
// controlIntent.putExtra("position",currentPosition);//传递当前音乐序号
// controlIntent.putExtra("listType",listType);//音乐列表的类型
// sendBroadcast(controlIntent);//发送广播
// isPause = false;//是否暂停为false
// }
//
// private class MyseekBarChangeListener implements SeekBar.OnSeekBarChangeListener {
// @Override
// public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
// //进度变动时调用该方法
//
// }
//
// @Override
// public void onStartTrackingTouch(SeekBar seekBar) {
// //开始拖动时调用
// }
//
// @Override
// public void onStopTrackingTouch(SeekBar seekBar) {
// //结束拖动时调用,拖动条未设置最大值时,默认为100
// Intent seekIntent = new Intent(Constants.SEEKBAR_ACTION);//发送广播通知拖动条变化
// seekIntent.putExtra("progress",seekBar.getProgress());
// sendBroadcast(seekIntent);//发送广播
// }
// }
//
// private class ServerReceiver extends BroadcastReceiver{
// //广播接受器,用于接收后台服务器
// @Override
// public void onReceive(Context context, Intent intent) {
// if(intent.getAction()==Constants.UPDATE_ACTION){
// //更新进度的广播处理
// int position = intent.getIntExtra("position",0);//获取音乐播放的位置
// //????
// currentTimeView.setText(MusicUtils.timeToString(position));
// playProgress.setProgress((int)(position*1.0/currentMusic.getTime()*100));//根据位置计算进度条的进度
// }else if(intent.getAction()==Constants.COMPLETE_ACTION){
// //音乐播放完成的事件处理
// currentPosition = intent.getIntExtra("position",0);//当前音乐播放序号
// currentMusic = musicList.get(currentPosition);
// showInfo();
// }
// }
// }
//
//
// private class SpinnerItemClickListener implements android.widget.AdapterView.OnItemSelectedListener {
// @Override
// public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
// Intent styleIntent = new Intent(Constants.UPDATE_STYLE);
// styleIntent.putExtra("style",styles[position]);
// sendBroadcast(styleIntent);
// }
//
// @Override
// public void onNothingSelected(AdapterView<?> parent) {
//
// }
// }
//
//
// //对单击事件的处理
// public void chooseMusic(View view){
// //选择歌曲
// Intent intent = new Intent(this,MainActivity.class);
// startActivity(intent);
// this.finish();
// }
//
// public void first(View view){
// //第一首按钮
// currentPosition = 0;
// currentMusic = musicList.get(currentPosition);
// playNewMusic();
// }
//
// public void pre(View view){
// //前一首
// currentPosition = (currentPosition-1+musicList.size())%musicList.size();
// currentMusic = musicList.get(currentPosition);
// playNewMusic();
// }
//
// public void control(View view){
// //播放和暂停的事件处理
// Intent controlIntent = new Intent(Constants.CONTROL_ACTION);
// //控制音乐的播放和暂停
// if(!isPause){//未暂停,处于播放状态,发送广播通知暂停
// controlIntent.putExtra("control",Constants.PAUSE);
// control.setImageResource(R.drawable.play);
// }else{
// controlIntent.putExtra("control",Constants.PLAY);
// control.setImageResource(R.drawable.pause);
// }
// isPause = !isPause;
// sendBroadcast(controlIntent);
// }
//
// public void next(View view){
// //下一首
// currentPosition = ((currentPosition+1)%musicList.size());
// currentMusic = musicList.get(currentPosition);
// playNewMusic();
// }
//
// public void last(View view){
// //最后一首
// currentPosition = musicList.size()-1;
// currentMusic = musicList.get(currentPosition);
// playNewMusic();
// }
//
// @Override
// protected void onDestroy() {
// if(serverReceiver!=null){//服务销毁时取消广播接收器的注册
// unregisterReceiver(serverReceiver);//activity销毁时取消注册
// }
// super.onDestroy();
// }
//}


package com.example.zengqi.musicplayer;

import java.util.List;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.Spinner;
import android.widget.TextView;

public class MusicPlayActivity extends Activity {// 音乐播放主界面,可控制音乐的播放
    private List<Music> musicList;//记录音乐列表
    private TextView titleView, singerView, currentTimeView, totalTimeView;// 显示歌曲名、作者信息、当前播放时间、总时间的文本显示框
    private SeekBar playProgress;// 拖动条
    private Spinner styleSpinner;//选择播放形式的下拉列表
    private ImageButton control;// 播放/暂停按钮
    private ImageView picView;//显示图片
    private ServerReceiver serverReceiver;// 接收后台服务发送的广播的广播接收器
    private Music currentMusic;//记录当前播放的音乐
    private boolean isPause=false;//是否暂停
    private int currentPosition;//当前音乐的索引
    private int listType;//音乐列表类型:所有音乐还是播放列表中的音乐
    private String[] styles=new String[]{Constants.LIST_LOOP,Constants.SINGLE_LOOP,Constants.RANDOM_PLAY,Constants.OVER_FINISH};
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);//去除标题
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);//全屏显示
        setContentView(R.layout.play_item);//加载主界面
        initView();// 初始化界面
    }
    public void initView() {//执行初始化操作
        styleSpinner=(Spinner)findViewById(R.id.styleSpinner);
        styleSpinner.setAdapter(new ArrayAdapter<String>(this,R.layout.spinner_text,styles));
        styleSpinner.setOnItemSelectedListener(new SpinnerItemClickListener());
        picView=(ImageView)findViewById(R.id.picView);
        currentTimeView = (TextView) findViewById(R.id.currentTime);// 显示音乐当前播放的时间的文本控件
        totalTimeView = (TextView) findViewById(R.id.totalTime);// 显示音乐的总时长的文本控件
        titleView = (TextView) findViewById(R.id.title);// 显示音乐标题的文本控件
        singerView = (TextView) findViewById(R.id.singer);// 显示音乐演唱者的文本控件
        playProgress = (SeekBar) findViewById(R.id.playProgress);// 显示当前音乐播放进度的控件
        control = (ImageButton) findViewById(R.id.control);// 控制播放或暂停的控件
        playProgress.setOnSeekBarChangeListener(new MySeekBarChangeListener());// 为拖动条添加事件处理
        serverReceiver = new ServerReceiver();//创建广播接收器
        IntentFilter filter = new IntentFilter();//可以接收到的广播类型
        filter.addAction(Constants.COMPLETE_ACTION);// 音乐播放结束的事件
        filter.addAction(Constants.UPDATE_ACTION);// 更新进度的动作
        registerReceiver(serverReceiver, filter);//注册广播接收器
        currentMusic = (Music) getIntent().getSerializableExtra("music");// 获取当前播放的音乐
        if(currentMusic==null){//如果当前音乐为空
            SharedPreferences musicPreferences=getSharedPreferences("music", Context.MODE_PRIVATE);
            currentPosition=musicPreferences.getInt("position", 0);
            listType=musicPreferences.getInt("listType", Constants.ALL_MUSIC);
            if(listType==Constants.ALL_MUSIC){//如果是所有的音乐
                musicList=Constants.musicList;
            }else{//如果是播放列表
                musicList=Constants.playlist;
            }
            currentMusic=musicList.get(currentPosition);//获取当前的音乐
            String styleString=musicPreferences.getString("style", Constants.LIST_LOOP);
            for(int i=0;i<styles.length;i++){
                if(styles[i].equalsIgnoreCase(styleString)){
                    styleSpinner.setSelection(i);
                    break;
                }
            }
            showInfo();//显示音乐信息
            isPause=true;//继续播放
            control(null);
        }else{//直接播放音乐
            currentPosition=getIntent().getIntExtra("position",0);//默认为第一首
            listType=getIntent().getIntExtra("listType", Constants.ALL_MUSIC);//获取列表的类型,是从所有的音乐还是播放列表中播放
            playNewMusic();//播放音乐
            if(listType==Constants.ALL_MUSIC){//如果是所有的音乐
                musicList=Constants.musicList;
            }else{//如果是播放列表
                musicList=Constants.playlist;
            }
        }

    }
    public void showInfo(){
        totalTimeView.setText(MusicUtils.timeToString(currentMusic.getTime()));//显示音乐的总时长
// titleView.setText(" " + currentMusic.getTitle() + " ");// 显示歌曲名
        singerView.setText(currentMusic.getSinger());// 显示演唱者
        Bitmap bitmap=MusicUtils.getAlbumPic(this, currentMusic);
        if(bitmap!=null){
            picView.setImageBitmap(bitmap);
        }else{
            picView.setImageResource(R.drawable.background);
        }
    }
    public void playNewMusic() {
        currentTimeView.setText(MusicUtils.timeToString(0));//显示当前播放的时间,默认为0
        showInfo();
        playProgress.setProgress(0);//进度为0
        control.setImageResource(R.drawable.pause);//显示暂停的按钮
        // 发送广播,通知后台播放音乐
        Intent controlIntent = new Intent(Constants.CONTROL_ACTION);
        controlIntent.putExtra("new", Constants.NEW);//这是一首新音乐
        controlIntent.putExtra("position",currentPosition);//传递当前音乐的序号
        controlIntent.putExtra("listType",listType);//传递音乐列表的类型
        sendBroadcast(controlIntent);//发送广播
        isPause=false;//是否暂停为false
    }
    private class MySeekBarChangeListener implements OnSeekBarChangeListener {
        public void onProgressChanged(SeekBar seekBar, int progress,
                                      boolean fromUser) { // 进度发送变化时调用该方法
        }
        public void onStartTrackingTouch(SeekBar seekBar) {// 开始拖动时调用
        }
        public void onStopTrackingTouch(SeekBar seekBar) {// 结束拖动时调用
            Intent seekIntent = new Intent(Constants.SEEKBAR_ACTION);//发送广播通知拖动条变化
            seekIntent.putExtra("progress", seekBar.getProgress());//将当前的进度传递进去
            sendBroadcast(seekIntent);// 发送广播
        }
    }
    private class ServerReceiver extends BroadcastReceiver {// 广播接收器,用于接收后台服务发送的广播
        public void onReceive(Context context, Intent intent) {
            if(intent.getAction()==Constants.UPDATE_ACTION){//更新进度的广播处理
                int position=intent.getIntExtra("position",0);//获取音乐播放的位置
                currentTimeView.setText(MusicUtils.timeToString(position));//显示当前的播放时长
                playProgress.setProgress((int)(position*1.0/currentMusic.getTime()*100));//根据位置计算进度条的进度
            }else if(intent.getAction()==Constants.COMPLETE_ACTION){//音乐播放完成的事件处理
                currentPosition=intent.getIntExtra("position", 0);//获取当前播放的音乐的序号
                currentMusic=musicList.get(currentPosition);//获取当前的音乐
                showInfo();//显示当前音乐的信息
            }
        }
    }
    private class SpinnerItemClickListener implements OnItemSelectedListener{
        public void onItemSelected(AdapterView<?> parent, View view,
                                   int position, long id) {
            Intent styleIntent=new Intent(Constants.UPDATE_STYLE);
            styleIntent.putExtra("style",styles[position]);
            sendBroadcast(styleIntent);
        }
        public void onNothingSelected(AdapterView<?> parent) {
        }
    }
    public void chooseMusic(View view){//选择歌曲按钮的事件处理
        Intent intent=new Intent(this,MainActivity.class);
        startActivity(intent);
        this.finish();
    }
    public void first(View view) {// 第一首按钮的事件处理
        currentPosition=0;
        currentMusic=musicList.get(currentPosition);
        playNewMusic();
    }
    public void pre(View view) {// 前一首按钮的事件处理
        currentPosition=(currentPosition-1+musicList.size())%musicList.size();
        currentMusic=musicList.get(currentPosition);
        playNewMusic();
    }
    public void control(View view) {// 播放和暂停按钮的事件处理
        Intent controlIntent=new Intent(Constants.CONTROL_ACTION);//控制音乐播放和暂停
        if(!isPause){//如果处于播放状态,发送广播通知暂停
            controlIntent.putExtra("control",Constants.PAUSE);
            control.setImageResource(R.drawable.play);//改变图标
        }else{//如果处于暂停状态,发送广播通知播放
            controlIntent.putExtra("control",Constants.PLAY);
            control.setImageResource(R.drawable.pause);//改变图标
        }
        isPause=!isPause;
        sendBroadcast(controlIntent);//发送广播
    }
    public void next(View view) {// 下一首按钮的事件处理
        currentPosition=(currentPosition+1)%musicList.size();
        currentMusic=musicList.get(currentPosition);
        playNewMusic();
    }
    public void last(View view) {// 最后一首按钮的事件处理
        currentPosition=musicList.size()-1;
        currentMusic=musicList.get(currentPosition);
        playNewMusic();
    }
    protected void onDestroy() {//服务销毁时,取消广播接收器的注册
        if (serverReceiver != null) {
            unregisterReceiver(serverReceiver);// Activity销毁时,取消注册
        }
        super.onDestroy();
    }
}

整个项目的结构:
自己动手实现音乐播放器app_第1张图片

ContentProvider是不同程序之间进行数据交换的标准API,为存储和读取数据提供了统一的接口。通过ContentProvider,应用程序可以实现数据共享。android内置的很多应用都使用ContentProvider向外提供数据,供开发者调用(如视频,音频,图片,通讯录等)。ContentProvider以某种URI的形式向外提供数据,数据以类似数据库中表的方式暴露,允许其他应用访问或修改数据,其他应用程序使用ContentResolver根据URI去访问操作指定的数据。
ContentProvider基类的常用方法有:onCreate,query,update,insert,getType,delete.以上几个方法都是抽象方法,用户在开发自己的contentProvider时必须重写这些方法。然后在AndroidManifest.xml文件中进行配置。
调用其他应用程序通过ContentProvider暴露的数据主要是下面3个步骤:
1.获取暴露数据对应的URI
2.调用当前的Context对象的getContentResolver()方法获取ContentProvider对象
3.调用ContentProvider对象的增,删,查,改方法对暴露的数据进行操作。

你可能感兴趣的:(APP,音乐)